ratatui/widgets/table/
cell.rs

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