ratatui_widgets/table/cell.rs
1use ratatui_core::buffer::Buffer;
2use ratatui_core::layout::Rect;
3use ratatui_core::style::{Style, Styled};
4use ratatui_core::text::Text;
5use ratatui_core::widgets::Widget;
6
7/// A [`Cell`] contains the [`Text`] to be displayed in a [`Row`] of a [`Table`].
8///
9/// You can apply a [`Style`] to the [`Cell`] using [`Cell::style`]. This will set the style for the
10/// entire area of the cell. Any [`Style`] set on the [`Text`] content will be combined with the
11/// [`Style`] of the [`Cell`] by adding the [`Style`] of the [`Text`] content to the [`Style`] of
12/// the [`Cell`]. Styles set on the text content will only affect the content.
13///
14/// You can use [`Text::alignment`] when creating a cell to align its content.
15///
16/// # Examples
17///
18/// You can create a `Cell` from anything that can be converted to a [`Text`].
19///
20/// ```rust
21/// use std::borrow::Cow;
22///
23/// use ratatui::style::Stylize;
24/// use ratatui::text::{Line, Span, Text};
25/// use ratatui::widgets::Cell;
26///
27/// Cell::from("simple string");
28/// Cell::from(Span::from("span"));
29/// Cell::from(Line::from(vec![
30/// Span::from("a vec of "),
31/// Span::from("spans").bold(),
32/// ]));
33/// Cell::from(Text::from("a text"));
34/// Cell::from(Text::from(Cow::Borrowed("hello")));
35/// ```
36///
37/// `Cell` implements [`Styled`] which means you can use style shorthands from the [`Stylize`] trait
38/// to set the style of the cell concisely.
39///
40/// ```rust
41/// use ratatui::style::Stylize;
42/// use ratatui::widgets::Cell;
43///
44/// Cell::new("Cell 1").red().italic();
45/// ```
46///
47/// [`Row`]: super::Row
48/// [`Table`]: super::Table
49/// [`Stylize`]: ratatui_core::style::Stylize
50#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
51pub struct Cell<'a> {
52 content: Text<'a>,
53 style: Style,
54 /// The number of columns this cell will extend over
55 pub(crate) column_span: u16,
56}
57
58impl<'a> Cell<'a> {
59 /// Creates a new [`Cell`]
60 ///
61 /// The `content` parameter accepts any value that can be converted into a [`Text`].
62 ///
63 /// # Examples
64 ///
65 /// ```rust
66 /// use ratatui::style::Stylize;
67 /// use ratatui::text::{Line, Span, Text};
68 /// use ratatui::widgets::Cell;
69 ///
70 /// Cell::new("simple string");
71 /// Cell::new(Span::from("span"));
72 /// Cell::new(Line::from(vec![
73 /// Span::raw("a vec of "),
74 /// Span::from("spans").bold(),
75 /// ]));
76 /// Cell::new(Text::from("a text"));
77 /// ```
78 pub fn new<T>(content: T) -> Self
79 where
80 T: Into<Text<'a>>,
81 {
82 Self {
83 content: content.into(),
84 style: Style::default(),
85 column_span: 1,
86 }
87 }
88
89 /// Set the content of the [`Cell`]
90 ///
91 /// The `content` parameter accepts any value that can be converted into a [`Text`].
92 ///
93 /// This is a fluent setter method which must be chained or used as it consumes self
94 ///
95 /// # Examples
96 ///
97 /// ```rust
98 /// use ratatui::style::Stylize;
99 /// use ratatui::text::{Line, Span, Text};
100 /// use ratatui::widgets::Cell;
101 ///
102 /// Cell::default().content("simple string");
103 /// Cell::default().content(Span::from("span"));
104 /// Cell::default().content(Line::from(vec![
105 /// Span::raw("a vec of "),
106 /// Span::from("spans").bold(),
107 /// ]));
108 /// Cell::default().content(Text::from("a text"));
109 /// ```
110 #[must_use = "method moves the value of self and returns the modified value"]
111 pub fn content<T>(mut self, content: T) -> Self
112 where
113 T: Into<Text<'a>>,
114 {
115 self.content = content.into();
116 self
117 }
118
119 /// Set the `column_span` of this cell
120 ///
121 /// This is a fluent setter method which must be chained or used as it consumes self
122 ///
123 /// # Example
124 /// ```rust
125 /// use ratatui::widgets::{Cell, Row};
126 /// let rows = vec![
127 /// Row::new(vec![Cell::new("12345").column_span(2)]),
128 /// Row::new(vec![Cell::new("xx"), Cell::new("yy")]),
129 /// ];
130 /// // "12345",
131 /// // "xx yy",
132 /// ```
133 #[must_use = "method moves the value of self and returns the modified value"]
134 pub const fn column_span(mut self, column_span: u16) -> Self {
135 self.column_span = column_span;
136 self
137 }
138
139 /// Set the `Style` of this cell
140 ///
141 /// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
142 /// your own type that implements [`Into<Style>`]).
143 ///
144 /// This `Style` will override the `Style` of the [`Row`] and can be overridden by the `Style`
145 /// of the [`Text`] content.
146 ///
147 /// This is a fluent setter method which must be chained or used as it consumes self
148 ///
149 /// # Examples
150 ///
151 /// ```rust
152 /// use ratatui::style::{Style, Stylize};
153 /// use ratatui::widgets::Cell;
154 ///
155 /// Cell::new("Cell 1").style(Style::new().red().italic());
156 /// ```
157 ///
158 /// `Cell` also implements the [`Styled`] trait, which means you can use style shorthands from
159 /// the [`Stylize`] trait to set the style of the widget more concisely.
160 ///
161 /// ```rust
162 /// use ratatui::style::Stylize;
163 /// use ratatui::widgets::Cell;
164 ///
165 /// Cell::new("Cell 1").red().italic();
166 /// ```
167 ///
168 /// [`Row`]: super::Row
169 /// [`Color`]: ratatui_core::style::Color
170 /// [`Stylize`]: ratatui_core::style::Stylize
171 #[must_use = "method moves the value of self and returns the modified value"]
172 pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
173 self.style = style.into();
174 self
175 }
176}
177
178impl Cell<'_> {
179 pub(crate) fn render(&self, area: Rect, buf: &mut Buffer) {
180 buf.set_style(area, self.style);
181 Widget::render(&self.content, area, buf);
182 }
183}
184
185impl<'a, T> From<T> for Cell<'a>
186where
187 T: Into<Text<'a>>,
188{
189 fn from(content: T) -> Self {
190 Self {
191 content: content.into(),
192 style: Style::default(),
193 column_span: 1,
194 }
195 }
196}
197
198impl Styled for Cell<'_> {
199 type Item = Self;
200
201 fn style(&self) -> Style {
202 self.style
203 }
204
205 fn set_style<S: Into<Style>>(self, style: S) -> Self::Item {
206 self.style(style)
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use ratatui_core::style::{Color, Modifier, Stylize};
213
214 use super::*;
215
216 #[test]
217 fn new() {
218 let cell = Cell::new("");
219 assert_eq!(cell.content, Text::from(""));
220 }
221
222 #[test]
223 fn content() {
224 let cell = Cell::default().content("");
225 assert_eq!(cell.content, Text::from(""));
226 }
227
228 #[test]
229 fn style() {
230 let style = Style::default().red().italic();
231 let cell = Cell::default().style(style);
232 assert_eq!(cell.style, style);
233 }
234
235 #[test]
236 fn stylize() {
237 assert_eq!(
238 Cell::from("").black().on_white().bold().not_dim().style,
239 Style::default()
240 .fg(Color::Black)
241 .bg(Color::White)
242 .add_modifier(Modifier::BOLD)
243 .remove_modifier(Modifier::DIM)
244 );
245 }
246}