Skip to main content

ppt_rs/generator/table/
builder.rs

1//! Table and TableBuilder for constructing tables
2
3use crate::core::ElementPlacement;
4use super::row::TableRow;
5
6/// Table definition with rows and positioning
7#[derive(Clone, Debug)]
8pub struct Table {
9    /// Table rows
10    pub rows: Vec<TableRow>,
11    /// Column widths in EMU
12    pub column_widths: Vec<u32>,
13    /// X position in EMU
14    pub x: u32,
15    /// Y position in EMU
16    pub y: u32,
17}
18
19impl Table {
20    /// Create a new table with explicit rows, column widths, and position
21    pub fn new(rows: Vec<TableRow>, column_widths: Vec<u32>, x: u32, y: u32) -> Self {
22        Table { rows, column_widths, x, y }
23    }
24
25    /// Create a table from raw data (2D string array)
26    pub fn from_data(data: Vec<Vec<&str>>, column_widths: Vec<u32>, x: u32, y: u32) -> Self {
27        use super::cell::TableCell;
28        
29        let rows = data
30            .into_iter()
31            .map(|row_data| {
32                TableRow::new(row_data.into_iter().map(TableCell::new).collect())
33            })
34            .collect();
35
36        Table {
37            rows,
38            column_widths,
39            x,
40            y,
41        }
42    }
43
44    /// Calculate total table width
45    pub fn width(&self) -> u32 {
46        self.column_widths.iter().sum()
47    }
48
49    /// Calculate total table height based on row heights
50    pub fn height(&self) -> u32 {
51        self.rows
52            .iter()
53            .map(|row| row.height.unwrap_or(400000))
54            .sum()
55    }
56
57    /// Get the number of rows
58    pub fn row_count(&self) -> usize {
59        self.rows.len()
60    }
61
62    /// Get the number of columns
63    pub fn column_count(&self) -> usize {
64        self.column_widths.len()
65    }
66}
67
68/// Builder for creating tables with fluent API
69#[derive(Clone, Debug)]
70pub struct TableBuilder {
71    column_widths: Vec<u32>,
72    rows: Vec<TableRow>,
73    placement: ElementPlacement,
74}
75
76impl TableBuilder {
77    /// Create a new table builder with column widths
78    pub fn new(column_widths: Vec<u32>) -> Self {
79        TableBuilder {
80            column_widths,
81            rows: Vec::new(),
82            placement: ElementPlacement::new(),
83        }
84    }
85
86    /// Add a row to the table
87    pub fn add_row(mut self, row: TableRow) -> Self {
88        self.rows.push(row);
89        self
90    }
91
92    /// Set table position
93    pub fn position(mut self, x: u32, y: u32) -> Self {
94        self.placement.set_position(x, y);
95        self
96    }
97
98    /// Add a simple row from strings
99    pub fn add_simple_row(mut self, cells: Vec<&str>) -> Self {
100        let row = TableRow::new(
101            cells.into_iter().map(super::cell::TableCell::new).collect(),
102        );
103        self.rows.push(row);
104        self
105    }
106
107    /// Build the final table
108    pub fn build(self) -> Table {
109        Table {
110            rows: self.rows,
111            column_widths: self.column_widths,
112            x: self.placement.x,
113            y: self.placement.y,
114        }
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use crate::generator::table::cell::TableCell;
122
123    #[test]
124    fn test_table_from_data() {
125        let table = Table::from_data(
126            vec![vec!["A", "B"], vec!["1", "2"]],
127            vec![1000000, 1000000],
128            0,
129            0,
130        );
131        assert_eq!(table.row_count(), 2);
132        assert_eq!(table.column_count(), 2);
133    }
134
135    #[test]
136    fn test_table_dimensions() {
137        let table = Table::from_data(
138            vec![vec!["A", "B", "C"]],
139            vec![1000000, 1500000, 2000000],
140            0,
141            0,
142        );
143        assert_eq!(table.width(), 4500000);
144    }
145
146    #[test]
147    fn test_table_builder() {
148        let table = TableBuilder::new(vec![1000000, 1000000])
149            .add_row(TableRow::new(vec![
150                TableCell::new("Header 1"),
151                TableCell::new("Header 2"),
152            ]))
153            .add_row(TableRow::new(vec![
154                TableCell::new("Data 1"),
155                TableCell::new("Data 2"),
156            ]))
157            .position(500000, 1000000)
158            .build();
159
160        assert_eq!(table.row_count(), 2);
161        assert_eq!(table.x, 500000);
162        assert_eq!(table.y, 1000000);
163    }
164}