Skip to main content

ppt_rs/generator/table/
style.rs

1//! Shared table styling presets and builders
2
3use super::builder::Table;
4use super::cell::TableCell;
5use super::row::TableRow;
6use super::TableBuilder;
7
8/// Header background used by HTML/Markdown import tables.
9pub const IMPORT_HEADER_BG: &str = "4472C4";
10/// Header background used by helper table presets.
11pub const HELPER_HEADER_BG: &str = "1F4E79";
12/// Standard header text color.
13pub const HEADER_TEXT: &str = "FFFFFF";
14
15/// Default slide position for imported tables (EMU).
16pub const DEFAULT_TABLE_X: u32 = 500_000;
17pub const DEFAULT_TABLE_Y: u32 = 1_800_000;
18/// Default total table width for imported tables (EMU).
19pub const DEFAULT_TABLE_WIDTH: u32 = 8_000_000;
20
21/// Styled header cell preset.
22pub fn header_cell(text: &str) -> TableCell {
23    TableCell::new(text)
24        .bold()
25        .background_color(IMPORT_HEADER_BG)
26        .text_color(HEADER_TEXT)
27}
28
29/// Build a positioned table from string rows with optional header styling.
30pub fn table_from_string_rows(rows: Vec<Vec<String>>, style_header: bool) -> Table {
31    let col_count = rows.iter().map(|row| row.len()).max().unwrap_or(1);
32    let col_width = DEFAULT_TABLE_WIDTH / col_count as u32;
33    let col_widths = vec![col_width; col_count];
34
35    let mut builder = TableBuilder::new(col_widths);
36
37    for (row_index, row_data) in rows.iter().enumerate() {
38        let cells: Vec<TableCell> = row_data
39            .iter()
40            .map(|text| {
41                if style_header && row_index == 0 {
42                    header_cell(text)
43                } else {
44                    TableCell::new(text)
45                }
46            })
47            .collect();
48
49        let mut cells = cells;
50        while cells.len() < col_count {
51            cells.push(TableCell::new(""));
52        }
53
54        builder = builder.add_row(TableRow::new(cells));
55    }
56
57    builder
58        .position(DEFAULT_TABLE_X, DEFAULT_TABLE_Y)
59        .build()
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_header_cell_preset() {
68        let cell = header_cell("Name");
69        assert!(cell.bold);
70        assert_eq!(cell.background_color.as_deref(), Some(IMPORT_HEADER_BG));
71        assert_eq!(cell.text_color.as_deref(), Some(HEADER_TEXT));
72    }
73
74    #[test]
75    fn test_table_from_string_rows_styles_first_row() {
76        let table = table_from_string_rows(
77            vec![vec!["A".into(), "B".into()], vec!["1".into(), "2".into()]],
78            true,
79        );
80        assert_eq!(table.rows.len(), 2);
81        assert!(table.rows[0].cells[0].bold);
82        assert!(!table.rows[1].cells[0].bold);
83    }
84}