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}