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}
55
56impl<'a> Cell<'a> {
57 /// Creates a new [`Cell`]
58 ///
59 /// The `content` parameter accepts any value that can be converted into a [`Text`].
60 ///
61 /// # Examples
62 ///
63 /// ```rust
64 /// use ratatui::style::Stylize;
65 /// use ratatui::text::{Line, Span, Text};
66 /// use ratatui::widgets::Cell;
67 ///
68 /// Cell::new("simple string");
69 /// Cell::new(Span::from("span"));
70 /// Cell::new(Line::from(vec![
71 /// Span::raw("a vec of "),
72 /// Span::from("spans").bold(),
73 /// ]));
74 /// Cell::new(Text::from("a text"));
75 /// ```
76 pub fn new<T>(content: T) -> Self
77 where
78 T: Into<Text<'a>>,
79 {
80 Self {
81 content: content.into(),
82 style: Style::default(),
83 }
84 }
85
86 /// Set the content of the [`Cell`]
87 ///
88 /// The `content` parameter accepts any value that can be converted into a [`Text`].
89 ///
90 /// This is a fluent setter method which must be chained or used as it consumes self
91 ///
92 /// # Examples
93 ///
94 /// ```rust
95 /// use ratatui::style::Stylize;
96 /// use ratatui::text::{Line, Span, Text};
97 /// use ratatui::widgets::Cell;
98 ///
99 /// Cell::default().content("simple string");
100 /// Cell::default().content(Span::from("span"));
101 /// Cell::default().content(Line::from(vec![
102 /// Span::raw("a vec of "),
103 /// Span::from("spans").bold(),
104 /// ]));
105 /// Cell::default().content(Text::from("a text"));
106 /// ```
107 #[must_use = "method moves the value of self and returns the modified value"]
108 pub fn content<T>(mut self, content: T) -> Self
109 where
110 T: Into<Text<'a>>,
111 {
112 self.content = content.into();
113 self
114 }
115
116 /// Set the `Style` of this cell
117 ///
118 /// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
119 /// your own type that implements [`Into<Style>`]).
120 ///
121 /// This `Style` will override the `Style` of the [`Row`] and can be overridden by the `Style`
122 /// of the [`Text`] content.
123 ///
124 /// This is a fluent setter method which must be chained or used as it consumes self
125 ///
126 /// # Examples
127 ///
128 /// ```rust
129 /// use ratatui::style::{Style, Stylize};
130 /// use ratatui::widgets::Cell;
131 ///
132 /// Cell::new("Cell 1").style(Style::new().red().italic());
133 /// ```
134 ///
135 /// `Cell` also implements the [`Styled`] trait, which means you can use style shorthands from
136 /// the [`Stylize`] trait to set the style of the widget more concisely.
137 ///
138 /// ```rust
139 /// use ratatui::style::Stylize;
140 /// use ratatui::widgets::Cell;
141 ///
142 /// Cell::new("Cell 1").red().italic();
143 /// ```
144 ///
145 /// [`Row`]: super::Row
146 /// [`Color`]: ratatui_core::style::Color
147 /// [`Stylize`]: ratatui_core::style::Stylize
148 #[must_use = "method moves the value of self and returns the modified value"]
149 pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
150 self.style = style.into();
151 self
152 }
153}
154
155impl Cell<'_> {
156 pub(crate) fn render(&self, area: Rect, buf: &mut Buffer) {
157 buf.set_style(area, self.style);
158 Widget::render(&self.content, area, buf);
159 }
160}
161
162impl<'a, T> From<T> for Cell<'a>
163where
164 T: Into<Text<'a>>,
165{
166 fn from(content: T) -> Self {
167 Self {
168 content: content.into(),
169 style: Style::default(),
170 }
171 }
172}
173
174impl Styled for Cell<'_> {
175 type Item = Self;
176
177 fn style(&self) -> Style {
178 self.style
179 }
180
181 fn set_style<S: Into<Style>>(self, style: S) -> Self::Item {
182 self.style(style)
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use ratatui_core::style::{Color, Modifier, Stylize};
189
190 use super::*;
191
192 #[test]
193 fn new() {
194 let cell = Cell::new("");
195 assert_eq!(cell.content, Text::from(""));
196 }
197
198 #[test]
199 fn content() {
200 let cell = Cell::default().content("");
201 assert_eq!(cell.content, Text::from(""));
202 }
203
204 #[test]
205 fn style() {
206 let style = Style::default().red().italic();
207 let cell = Cell::default().style(style);
208 assert_eq!(cell.style, style);
209 }
210
211 #[test]
212 fn stylize() {
213 assert_eq!(
214 Cell::from("").black().on_white().bold().not_dim().style,
215 Style::default()
216 .fg(Color::Black)
217 .bg(Color::White)
218 .add_modifier(Modifier::BOLD)
219 .remove_modifier(Modifier::DIM)
220 );
221 }
222}