Skip to main content

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}