Skip to main content

ppt_rs/generator/table/
cell.rs

1//! Table cell definition and formatting
2
3/// Horizontal text alignment
4#[derive(Clone, Debug, Default, PartialEq)]
5pub enum CellAlign {
6    Left,
7    #[default]
8    Center,
9    Right,
10    Justify,
11}
12
13impl CellAlign {
14    /// Get the OOXML alignment value
15    pub fn as_str(&self) -> &'static str {
16        match self {
17            CellAlign::Left => "l",
18            CellAlign::Center => "ctr",
19            CellAlign::Right => "r",
20            CellAlign::Justify => "just",
21        }
22    }
23}
24
25/// Vertical text alignment
26#[derive(Clone, Debug, Default, PartialEq)]
27pub enum CellVAlign {
28    Top,
29    #[default]
30    Middle,
31    Bottom,
32}
33
34impl CellVAlign {
35    /// Get the OOXML anchor value
36    pub fn as_str(&self) -> &'static str {
37        match self {
38            CellVAlign::Top => "t",
39            CellVAlign::Middle => "ctr",
40            CellVAlign::Bottom => "b",
41        }
42    }
43}
44
45/// Table cell content with formatting options
46#[derive(Clone, Debug)]
47pub struct TableCell {
48    /// Cell text content
49    pub text: String,
50    /// Bold text
51    pub bold: bool,
52    /// Italic text
53    pub italic: bool,
54    /// Underlined text
55    pub underline: bool,
56    /// Text color (RGB hex, e.g., "FF0000")
57    pub text_color: Option<String>,
58    /// Background color (RGB hex, e.g., "0000FF")
59    pub background_color: Option<String>,
60    /// Font size in points
61    pub font_size: Option<u32>,
62    /// Font family name
63    pub font_family: Option<String>,
64    /// Horizontal text alignment
65    pub align: CellAlign,
66    /// Vertical text alignment
67    pub valign: CellVAlign,
68    /// Enable text wrapping
69    pub wrap_text: bool,
70    /// Number of columns this cell spans (gridSpan attribute)
71    pub grid_span: Option<u32>,
72    /// Number of rows this cell spans (rowSpan attribute)
73    pub row_span: Option<u32>,
74    /// Whether this cell is horizontally merged (covered by a gridSpan)
75    pub h_merge: bool,
76    /// Whether this cell is vertically merged (covered by a rowSpan)
77    pub v_merge: bool,
78}
79
80impl TableCell {
81    /// Create a new table cell with text
82    pub fn new(text: &str) -> Self {
83        TableCell {
84            text: text.to_string(),
85            bold: false,
86            italic: false,
87            underline: false,
88            text_color: None,
89            background_color: None,
90            font_size: None,
91            font_family: None,
92            align: CellAlign::Center,
93            valign: CellVAlign::Middle,
94            wrap_text: true,
95            grid_span: None,
96            row_span: None,
97            h_merge: false,
98            v_merge: false,
99        }
100    }
101
102    /// Set cell text as bold
103    pub fn bold(mut self) -> Self {
104        self.bold = true;
105        self
106    }
107
108    /// Set cell text as italic
109    pub fn italic(mut self) -> Self {
110        self.italic = true;
111        self
112    }
113
114    /// Set cell text as underlined
115    pub fn underline(mut self) -> Self {
116        self.underline = true;
117        self
118    }
119
120    /// Set cell text color (RGB hex format, e.g., "FF0000" or "#FF0000")
121    pub fn text_color(mut self, color: &str) -> Self {
122        self.text_color = Some(color.trim_start_matches('#').to_uppercase());
123        self
124    }
125
126    /// Set cell background color (RGB hex format, e.g., "FF0000" or "#FF0000")
127    pub fn background_color(mut self, color: &str) -> Self {
128        self.background_color = Some(color.trim_start_matches('#').to_uppercase());
129        self
130    }
131
132    /// Set font size in points
133    pub fn font_size(mut self, size: u32) -> Self {
134        self.font_size = Some(size);
135        self
136    }
137
138    /// Set font family name
139    pub fn font_family(mut self, family: &str) -> Self {
140        self.font_family = Some(family.to_string());
141        self
142    }
143
144    /// Set horizontal text alignment
145    pub fn align(mut self, align: CellAlign) -> Self {
146        self.align = align;
147        self
148    }
149
150    /// Set horizontal text alignment to left
151    pub fn align_left(mut self) -> Self {
152        self.align = CellAlign::Left;
153        self
154    }
155
156    /// Set horizontal text alignment to right
157    pub fn align_right(mut self) -> Self {
158        self.align = CellAlign::Right;
159        self
160    }
161
162    /// Set horizontal text alignment to center
163    pub fn align_center(mut self) -> Self {
164        self.align = CellAlign::Center;
165        self
166    }
167
168    /// Set vertical text alignment
169    pub fn valign(mut self, valign: CellVAlign) -> Self {
170        self.valign = valign;
171        self
172    }
173
174    /// Set vertical text alignment to top
175    pub fn valign_top(mut self) -> Self {
176        self.valign = CellVAlign::Top;
177        self
178    }
179
180    /// Set vertical text alignment to bottom
181    pub fn valign_bottom(mut self) -> Self {
182        self.valign = CellVAlign::Bottom;
183        self
184    }
185
186    /// Enable or disable text wrapping
187    pub fn wrap(mut self, wrap: bool) -> Self {
188        self.wrap_text = wrap;
189        self
190    }
191
192    /// Set horizontal span (gridSpan) - this cell covers multiple columns
193    pub fn grid_span(mut self, span: u32) -> Self {
194        self.grid_span = Some(span);
195        self
196    }
197
198    /// Set vertical span (rowSpan) - this cell covers multiple rows
199    pub fn row_span(mut self, span: u32) -> Self {
200        self.row_span = Some(span);
201        self
202    }
203
204    /// Mark this cell as horizontally merged (covered by another cell's gridSpan)
205    pub fn h_merge(mut self) -> Self {
206        self.h_merge = true;
207        self
208    }
209
210    /// Mark this cell as vertically merged (covered by another cell's rowSpan)
211    pub fn v_merge(mut self) -> Self {
212        self.v_merge = true;
213        self
214    }
215
216    /// Alias: set column span (gridSpan)
217    pub fn with_col_span(self, span: u32) -> Self {
218        self.grid_span(span)
219    }
220
221    /// Alias: set row span
222    pub fn with_row_span(self, span: u32) -> Self {
223        self.row_span(span)
224    }
225
226    /// Alias: set horizontal merge flag
227    pub fn with_h_merge(self) -> Self {
228        self.h_merge()
229    }
230
231    /// Alias: set vertical merge flag
232    pub fn with_v_merge(self) -> Self {
233        self.v_merge()
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    fn test_cell_new() {
243        let cell = TableCell::new("Hello");
244        assert_eq!(cell.text, "Hello");
245        assert!(!cell.bold);
246        assert!(!cell.italic);
247        assert_eq!(cell.align, CellAlign::Center);
248        assert_eq!(cell.valign, CellVAlign::Middle);
249    }
250
251    #[test]
252    fn test_cell_formatting() {
253        let cell = TableCell::new("Test")
254            .bold()
255            .italic()
256            .underline()
257            .text_color("FF0000")
258            .background_color("0000FF")
259            .font_size(24)
260            .font_family("Arial");
261
262        assert!(cell.bold);
263        assert!(cell.italic);
264        assert!(cell.underline);
265        assert_eq!(cell.text_color, Some("FF0000".to_string()));
266        assert_eq!(cell.background_color, Some("0000FF".to_string()));
267        assert_eq!(cell.font_size, Some(24));
268        assert_eq!(cell.font_family, Some("Arial".to_string()));
269    }
270
271    #[test]
272    fn test_cell_alignment() {
273        let cell = TableCell::new("Test").align_left().valign_top();
274        assert_eq!(cell.align, CellAlign::Left);
275        assert_eq!(cell.valign, CellVAlign::Top);
276    }
277
278    #[test]
279    fn test_cell_align_as_str() {
280        assert_eq!(CellAlign::Left.as_str(), "l");
281        assert_eq!(CellAlign::Center.as_str(), "ctr");
282        assert_eq!(CellAlign::Right.as_str(), "r");
283        assert_eq!(CellAlign::Justify.as_str(), "just");
284    }
285
286    #[test]
287    fn test_cell_valign_as_str() {
288        assert_eq!(CellVAlign::Top.as_str(), "t");
289        assert_eq!(CellVAlign::Middle.as_str(), "ctr");
290        assert_eq!(CellVAlign::Bottom.as_str(), "b");
291    }
292}