1use lopdf::{Document, Object, ObjectId};
7use tracing::{debug, instrument, trace};
8
9mod constants;
10mod drawing;
11mod drawing_utils;
12pub mod error;
13pub mod layout;
14pub mod style;
15pub mod table;
16mod text;
17
18pub use constants::*;
20
21pub use error::{Result, TableError};
22pub use style::{
23 Alignment, BorderStyle, CellStyle, Color, RowStyle, TableStyle, VerticalAlignment,
24};
25pub use table::{Cell, ColumnWidth, Row, Table};
26
27#[derive(Debug, Clone)]
29pub struct PagedTableResult {
30 pub page_ids: Vec<ObjectId>,
32 pub total_pages: usize,
34 pub final_position: (f32, f32),
36}
37
38pub trait TableDrawing {
40 fn draw_table(&mut self, page_id: ObjectId, table: Table, position: (f32, f32)) -> Result<()>;
50
51 fn add_table_to_page(&mut self, page_id: ObjectId, table: Table) -> Result<()>;
55
56 fn create_table_content(&self, table: &Table, position: (f32, f32)) -> Result<Vec<Object>>;
60
61 fn draw_table_with_pagination(
75 &mut self,
76 page_id: ObjectId,
77 table: Table,
78 position: (f32, f32),
79 ) -> Result<PagedTableResult>;
80}
81
82impl TableDrawing for Document {
83 #[instrument(skip(self, table), fields(table_rows = table.rows.len()))]
84 fn draw_table(&mut self, page_id: ObjectId, table: Table, position: (f32, f32)) -> Result<()> {
85 debug!("Drawing table at position {:?}", position);
86
87 let layout = layout::calculate_layout(&table)?;
89 trace!("Calculated layout: {:?}", layout);
90
91 let operations = drawing::generate_table_operations(&table, &layout, position)?;
93
94 drawing::add_operations_to_page(self, page_id, operations)?;
96
97 Ok(())
98 }
99
100 #[instrument(skip(self, table))]
101 fn add_table_to_page(&mut self, page_id: ObjectId, table: Table) -> Result<()> {
102 let position = (DEFAULT_MARGIN, A4_HEIGHT - DEFAULT_MARGIN - 50.0);
104 self.draw_table(page_id, table, position)
105 }
106
107 fn create_table_content(&self, table: &Table, position: (f32, f32)) -> Result<Vec<Object>> {
108 let layout = layout::calculate_layout(table)?;
109 drawing::generate_table_operations(table, &layout, position)
110 }
111
112 #[instrument(skip(self, table), fields(table_rows = table.rows.len()))]
113 fn draw_table_with_pagination(
114 &mut self,
115 page_id: ObjectId,
116 table: Table,
117 position: (f32, f32),
118 ) -> Result<PagedTableResult> {
119 debug!("Drawing paginated table at position {:?}", position);
120
121 let layout = layout::calculate_layout(&table)?;
123 trace!("Calculated layout: {:?}", layout);
124
125 let result = drawing::draw_table_paginated(self, page_id, &table, &layout, position)?;
127
128 Ok(result)
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_basic_table_creation() {
138 let table = Table::new()
139 .add_row(Row::new(vec![Cell::new("Header 1"), Cell::new("Header 2")]))
140 .add_row(Row::new(vec![Cell::new("Data 1"), Cell::new("Data 2")]));
141
142 assert_eq!(table.rows.len(), 2);
143 assert_eq!(table.rows[0].cells.len(), 2);
144 }
145}