pub struct TableCell {Show 15 fields
pub text: String,
pub bold: bool,
pub italic: bool,
pub underline: bool,
pub text_color: Option<String>,
pub background_color: Option<String>,
pub font_size: Option<u32>,
pub font_family: Option<String>,
pub align: CellAlign,
pub valign: CellVAlign,
pub wrap_text: bool,
pub grid_span: Option<u32>,
pub row_span: Option<u32>,
pub h_merge: bool,
pub v_merge: bool,
}Expand description
Table cell content with formatting options
Fields§
§text: StringCell text content
bold: boolBold text
italic: boolItalic text
underline: boolUnderlined text
text_color: Option<String>Text color (RGB hex, e.g., “FF0000”)
background_color: Option<String>Background color (RGB hex, e.g., “0000FF”)
font_size: Option<u32>Font size in points
font_family: Option<String>Font family name
align: CellAlignHorizontal text alignment
valign: CellVAlignVertical text alignment
wrap_text: boolEnable text wrapping
grid_span: Option<u32>Number of columns this cell spans (gridSpan attribute)
row_span: Option<u32>Number of rows this cell spans (rowSpan attribute)
h_merge: boolWhether this cell is horizontally merged (covered by a gridSpan)
v_merge: boolWhether this cell is vertically merged (covered by a rowSpan)
Implementations§
Source§impl TableCell
impl TableCell
Sourcepub fn new(text: &str) -> Self
pub fn new(text: &str) -> Self
Create a new table cell with text
Examples found in repository?
29fn create_employee_table() -> Table {
30 let header_cells = vec![
31 TableCell::new("Name").bold().background_color("4F81BD"),
32 TableCell::new("Department").bold().background_color("4F81BD"),
33 TableCell::new("Status").bold().background_color("4F81BD"),
34 ];
35 let header_row = TableRow::new(header_cells);
36
37 let rows = vec![
38 TableRow::new(vec![
39 TableCell::new("Alice Johnson"),
40 TableCell::new("Engineering"),
41 TableCell::new("Active"),
42 ]),
43 TableRow::new(vec![
44 TableCell::new("Bob Smith"),
45 TableCell::new("Sales"),
46 TableCell::new("Active"),
47 ]),
48 TableRow::new(vec![
49 TableCell::new("Carol Davis"),
50 TableCell::new("Marketing"),
51 TableCell::new("On Leave"),
52 ]),
53 TableRow::new(vec![
54 TableCell::new("David Wilson"),
55 TableCell::new("Engineering"),
56 TableCell::new("Active"),
57 ]),
58 TableRow::new(vec![
59 TableCell::new("Emma Brown"),
60 TableCell::new("HR"),
61 TableCell::new("Active"),
62 ]),
63 ];
64
65 Table::new(
66 vec![vec![header_row], rows].concat(),
67 vec![2000000, 2500000, 1500000],
68 500000,
69 1500000,
70 )
71}
72
73fn create_sales_table() -> Table {
74 let header_cells = vec![
75 TableCell::new("Product").bold().background_color("003366"),
76 TableCell::new("Revenue").bold().background_color("003366"),
77 TableCell::new("Growth").bold().background_color("003366"),
78 ];
79 let header_row = TableRow::new(header_cells);
80
81 let rows = vec![
82 TableRow::new(vec![
83 TableCell::new("Cloud Services"),
84 TableCell::new("$450K"),
85 TableCell::new("+28%"),
86 ]),
87 TableRow::new(vec![
88 TableCell::new("Enterprise Suite"),
89 TableCell::new("$320K"),
90 TableCell::new("+15%"),
91 ]),
92 TableRow::new(vec![
93 TableCell::new("Developer Tools"),
94 TableCell::new("$280K"),
95 TableCell::new("+42%"),
96 ]),
97 TableRow::new(vec![
98 TableCell::new("Mobile App"),
99 TableCell::new("$195K"),
100 TableCell::new("+35%"),
101 ]),
102 TableRow::new(vec![
103 TableCell::new("Support Services"),
104 TableCell::new("$155K"),
105 TableCell::new("+12%"),
106 ]),
107 ];
108
109 Table::new(
110 vec![vec![header_row], rows].concat(),
111 vec![2200000, 2000000, 1800000],
112 500000,
113 1500000,
114 )
115}
116
117fn create_quarterly_table() -> Table {
118 let header_cells = vec![
119 TableCell::new("Quarter").bold().background_color("1F497D"),
120 TableCell::new("Revenue").bold().background_color("1F497D"),
121 TableCell::new("Profit").bold().background_color("1F497D"),
122 ];
123 let header_row = TableRow::new(header_cells);
124
125 let q1_cells = vec![
126 TableCell::new("Q1 2025"),
127 TableCell::new("$450K"),
128 TableCell::new("$90K"),
129 ];
130 let q1 = TableRow::new(q1_cells);
131
132 let q2_cells = vec![
133 TableCell::new("Q2 2025"),
134 TableCell::new("$520K"),
135 TableCell::new("$110K"),
136 ];
137 let q2 = TableRow::new(q2_cells);
138
139 let q3_cells = vec![
140 TableCell::new("Q3 2025"),
141 TableCell::new("$580K"),
142 TableCell::new("$130K"),
143 ];
144 let q3 = TableRow::new(q3_cells);
145
146 Table::new(
147 vec![header_row, q1, q2, q3],
148 vec![2000000, 2000000, 2000000],
149 500000,
150 1500000,
151 )
152}More examples
81fn create_styled_table_example() -> Result<(), Box<dyn std::error::Error>> {
82 let header_cells = vec![
83 TableCell::new("Name").bold().background_color("003366"),
84 TableCell::new("Age").bold().background_color("003366"),
85 TableCell::new("City").bold().background_color("003366"),
86 ];
87 let header_row = TableRow::new(header_cells);
88
89 let data_rows = vec![
90 TableRow::new(vec![
91 TableCell::new("Alice"),
92 TableCell::new("30"),
93 TableCell::new("NYC"),
94 ]),
95 TableRow::new(vec![
96 TableCell::new("Bob"),
97 TableCell::new("28"),
98 TableCell::new("LA"),
99 ]),
100 TableRow::new(vec![
101 TableCell::new("Carol"),
102 TableCell::new("35"),
103 TableCell::new("Chicago"),
104 ]),
105 ];
106
107 let table = Table::new(
108 vec![vec![header_row], data_rows].concat(),
109 vec![1500000, 1500000, 1500000],
110 500000,
111 1500000,
112 );
113
114 let slides = vec![
115 SlideContent::new("Styled Table")
116 .title_bold(true)
117 .title_color("003366")
118 .add_bullet("Table with formatting"),
119 SlideContent::new("People Data")
120 .table(table),
121 ];
122
123 let pptx_data = create_pptx_with_content("Styled Table", slides)?;
124 fs::write("examples/output/styled_table.pptx", pptx_data)?;
125 Ok(())
126}
127
128fn create_data_table_example() -> Result<(), Box<dyn std::error::Error>> {
129 let header_cells = vec![
130 TableCell::new("Product").bold().background_color("1F497D"),
131 TableCell::new("Revenue").bold().background_color("1F497D"),
132 TableCell::new("Growth").bold().background_color("1F497D"),
133 ];
134 let header_row = TableRow::new(header_cells);
135
136 let data_rows = vec![
137 TableRow::new(vec![
138 TableCell::new("Product A"),
139 TableCell::new("$100K"),
140 TableCell::new("+15%"),
141 ]),
142 TableRow::new(vec![
143 TableCell::new("Product B"),
144 TableCell::new("$150K"),
145 TableCell::new("+22%"),
146 ]),
147 TableRow::new(vec![
148 TableCell::new("Product C"),
149 TableCell::new("$200K"),
150 TableCell::new("+18%"),
151 ]),
152 ];
153
154 let table = Table::new(
155 vec![vec![header_row], data_rows].concat(),
156 vec![2000000, 2000000, 1500000],
157 457200,
158 1400000,
159 );
160
161 let slides = vec![
162 SlideContent::new("Sales Data Table")
163 .title_bold(true)
164 .title_size(48)
165 .add_bullet("Quarterly sales figures"),
166 SlideContent::new("Q1 2025 Sales")
167 .table(table),
168 SlideContent::new("Summary")
169 .content_bold(true)
170 .add_bullet("Total Revenue: $450K")
171 .add_bullet("Average Growth: +18.3%")
172 .add_bullet("Best Performer: Product C"),
173 ];
174
175 let pptx_data = create_pptx_with_content("Sales Data", slides)?;
176 fs::write("examples/output/data_table.pptx", pptx_data)?;
177 Ok(())
178}
179
180fn create_multiple_tables_example() -> Result<(), Box<dyn std::error::Error>> {
181 // Table 1: Employees
182 let emp_header = TableRow::new(vec![
183 TableCell::new("ID").bold().background_color("4F81BD"),
184 TableCell::new("Name").bold().background_color("4F81BD"),
185 TableCell::new("Department").bold().background_color("4F81BD"),
186 ]);
187 let emp_rows = vec![
188 TableRow::new(vec![
189 TableCell::new("001"),
190 TableCell::new("Alice"),
191 TableCell::new("Engineering"),
192 ]),
193 TableRow::new(vec![
194 TableCell::new("002"),
195 TableCell::new("Bob"),
196 TableCell::new("Sales"),
197 ]),
198 TableRow::new(vec![
199 TableCell::new("003"),
200 TableCell::new("Carol"),
201 TableCell::new("Marketing"),
202 ]),
203 ];
204 let emp_table = Table::new(
205 vec![vec![emp_header], emp_rows].concat(),
206 vec![1000000, 2000000, 2000000],
207 500000,
208 1500000,
209 );
210
211 // Table 2: Projects
212 let proj_header = TableRow::new(vec![
213 TableCell::new("Project").bold().background_color("003366"),
214 TableCell::new("Status").bold().background_color("003366"),
215 TableCell::new("Owner").bold().background_color("003366"),
216 ]);
217 let proj_rows = vec![
218 TableRow::new(vec![
219 TableCell::new("Project A"),
220 TableCell::new("In Progress"),
221 TableCell::new("Alice"),
222 ]),
223 TableRow::new(vec![
224 TableCell::new("Project B"),
225 TableCell::new("Completed"),
226 TableCell::new("Bob"),
227 ]),
228 TableRow::new(vec![
229 TableCell::new("Project C"),
230 TableCell::new("Planning"),
231 TableCell::new("Carol"),
232 ]),
233 ];
234 let proj_table = Table::new(
235 vec![vec![proj_header], proj_rows].concat(),
236 vec![2000000, 2000000, 1500000],
237 500000,
238 1500000,
239 );
240
241 let slides = vec![
242 SlideContent::new("Multiple Tables")
243 .title_bold(true)
244 .add_bullet("Slide with multiple tables"),
245 SlideContent::new("Table 1: Employees")
246 .table(emp_table),
247 SlideContent::new("Table 2: Projects")
248 .table(proj_table),
249 SlideContent::new("Summary")
250 .add_bullet("Total Employees: 3")
251 .add_bullet("Active Projects: 3")
252 .add_bullet("Completion Rate: 33%"),
253 ];
254
255 let pptx_data = create_pptx_with_content("Multiple Tables", slides)?;
256 fs::write("examples/output/multiple_tables.pptx", pptx_data)?;
257 Ok(())
258}
259
260/// Helper function to demonstrate table creation
261#[allow(dead_code)]
262fn create_table_structure() -> Table {
263 // Create table using builder
264 TableBuilder::new(vec![1000000, 1000000, 1000000])
265 .position(500000, 1000000)
266 .add_simple_row(vec!["Header 1", "Header 2", "Header 3"])
267 .add_simple_row(vec!["Data 1", "Data 2", "Data 3"])
268 .add_simple_row(vec!["Data 4", "Data 5", "Data 6"])
269 .build()
270}
271
272/// Helper function to demonstrate styled table
273#[allow(dead_code)]
274fn create_styled_table() -> Table {
275 let header_cells = vec![
276 TableCell::new("Name").bold().background_color("003366"),
277 TableCell::new("Age").bold().background_color("003366"),
278 TableCell::new("City").bold().background_color("003366"),
279 ];
280 let header_row = TableRow::new(header_cells);
281
282 let data_cells = vec![
283 TableCell::new("Alice"),
284 TableCell::new("30"),
285 TableCell::new("NYC"),
286 ];
287 let data_row = TableRow::new(data_cells);
288
289 Table::new(
290 vec![header_row, data_row],
291 vec![1000000, 1000000, 1000000],
292 500000,
293 1000000,
294 )
295}33fn create_text_formatting_table() -> Table {
34 let header_cells = vec![
35 TableCell::new("Style").bold().background_color("4F81BD"),
36 TableCell::new("Example").bold().background_color("4F81BD"),
37 TableCell::new("Description").bold().background_color("4F81BD"),
38 ];
39 let header_row = TableRow::new(header_cells);
40
41 let rows = vec![
42 TableRow::new(vec![
43 TableCell::new("Bold"),
44 TableCell::new("Bold Text").bold(),
45 TableCell::new("Text with bold formatting"),
46 ]),
47 TableRow::new(vec![
48 TableCell::new("Italic"),
49 TableCell::new("Italic Text").italic(),
50 TableCell::new("Text with italic formatting"),
51 ]),
52 TableRow::new(vec![
53 TableCell::new("Underline"),
54 TableCell::new("Underlined Text").underline(),
55 TableCell::new("Text with underline formatting"),
56 ]),
57 TableRow::new(vec![
58 TableCell::new("Bold + Italic"),
59 TableCell::new("Bold Italic Text").bold().italic(),
60 TableCell::new("Text with both bold and italic"),
61 ]),
62 TableRow::new(vec![
63 TableCell::new("All Three"),
64 TableCell::new("Bold Italic Underlined").bold().italic().underline(),
65 TableCell::new("Text with all formatting options"),
66 ]),
67 ];
68
69 Table::new(
70 vec![vec![header_row], rows].concat(),
71 vec![2000000, 3000000, 3000000],
72 500000,
73 1500000,
74 )
75}
76
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn bold(self) -> Self
pub fn bold(self) -> Self
Set cell text as bold
Examples found in repository?
29fn create_employee_table() -> Table {
30 let header_cells = vec![
31 TableCell::new("Name").bold().background_color("4F81BD"),
32 TableCell::new("Department").bold().background_color("4F81BD"),
33 TableCell::new("Status").bold().background_color("4F81BD"),
34 ];
35 let header_row = TableRow::new(header_cells);
36
37 let rows = vec![
38 TableRow::new(vec![
39 TableCell::new("Alice Johnson"),
40 TableCell::new("Engineering"),
41 TableCell::new("Active"),
42 ]),
43 TableRow::new(vec![
44 TableCell::new("Bob Smith"),
45 TableCell::new("Sales"),
46 TableCell::new("Active"),
47 ]),
48 TableRow::new(vec![
49 TableCell::new("Carol Davis"),
50 TableCell::new("Marketing"),
51 TableCell::new("On Leave"),
52 ]),
53 TableRow::new(vec![
54 TableCell::new("David Wilson"),
55 TableCell::new("Engineering"),
56 TableCell::new("Active"),
57 ]),
58 TableRow::new(vec![
59 TableCell::new("Emma Brown"),
60 TableCell::new("HR"),
61 TableCell::new("Active"),
62 ]),
63 ];
64
65 Table::new(
66 vec![vec![header_row], rows].concat(),
67 vec![2000000, 2500000, 1500000],
68 500000,
69 1500000,
70 )
71}
72
73fn create_sales_table() -> Table {
74 let header_cells = vec![
75 TableCell::new("Product").bold().background_color("003366"),
76 TableCell::new("Revenue").bold().background_color("003366"),
77 TableCell::new("Growth").bold().background_color("003366"),
78 ];
79 let header_row = TableRow::new(header_cells);
80
81 let rows = vec![
82 TableRow::new(vec![
83 TableCell::new("Cloud Services"),
84 TableCell::new("$450K"),
85 TableCell::new("+28%"),
86 ]),
87 TableRow::new(vec![
88 TableCell::new("Enterprise Suite"),
89 TableCell::new("$320K"),
90 TableCell::new("+15%"),
91 ]),
92 TableRow::new(vec![
93 TableCell::new("Developer Tools"),
94 TableCell::new("$280K"),
95 TableCell::new("+42%"),
96 ]),
97 TableRow::new(vec![
98 TableCell::new("Mobile App"),
99 TableCell::new("$195K"),
100 TableCell::new("+35%"),
101 ]),
102 TableRow::new(vec![
103 TableCell::new("Support Services"),
104 TableCell::new("$155K"),
105 TableCell::new("+12%"),
106 ]),
107 ];
108
109 Table::new(
110 vec![vec![header_row], rows].concat(),
111 vec![2200000, 2000000, 1800000],
112 500000,
113 1500000,
114 )
115}
116
117fn create_quarterly_table() -> Table {
118 let header_cells = vec![
119 TableCell::new("Quarter").bold().background_color("1F497D"),
120 TableCell::new("Revenue").bold().background_color("1F497D"),
121 TableCell::new("Profit").bold().background_color("1F497D"),
122 ];
123 let header_row = TableRow::new(header_cells);
124
125 let q1_cells = vec![
126 TableCell::new("Q1 2025"),
127 TableCell::new("$450K"),
128 TableCell::new("$90K"),
129 ];
130 let q1 = TableRow::new(q1_cells);
131
132 let q2_cells = vec![
133 TableCell::new("Q2 2025"),
134 TableCell::new("$520K"),
135 TableCell::new("$110K"),
136 ];
137 let q2 = TableRow::new(q2_cells);
138
139 let q3_cells = vec![
140 TableCell::new("Q3 2025"),
141 TableCell::new("$580K"),
142 TableCell::new("$130K"),
143 ];
144 let q3 = TableRow::new(q3_cells);
145
146 Table::new(
147 vec![header_row, q1, q2, q3],
148 vec![2000000, 2000000, 2000000],
149 500000,
150 1500000,
151 )
152}More examples
81fn create_styled_table_example() -> Result<(), Box<dyn std::error::Error>> {
82 let header_cells = vec![
83 TableCell::new("Name").bold().background_color("003366"),
84 TableCell::new("Age").bold().background_color("003366"),
85 TableCell::new("City").bold().background_color("003366"),
86 ];
87 let header_row = TableRow::new(header_cells);
88
89 let data_rows = vec![
90 TableRow::new(vec![
91 TableCell::new("Alice"),
92 TableCell::new("30"),
93 TableCell::new("NYC"),
94 ]),
95 TableRow::new(vec![
96 TableCell::new("Bob"),
97 TableCell::new("28"),
98 TableCell::new("LA"),
99 ]),
100 TableRow::new(vec![
101 TableCell::new("Carol"),
102 TableCell::new("35"),
103 TableCell::new("Chicago"),
104 ]),
105 ];
106
107 let table = Table::new(
108 vec![vec![header_row], data_rows].concat(),
109 vec![1500000, 1500000, 1500000],
110 500000,
111 1500000,
112 );
113
114 let slides = vec![
115 SlideContent::new("Styled Table")
116 .title_bold(true)
117 .title_color("003366")
118 .add_bullet("Table with formatting"),
119 SlideContent::new("People Data")
120 .table(table),
121 ];
122
123 let pptx_data = create_pptx_with_content("Styled Table", slides)?;
124 fs::write("examples/output/styled_table.pptx", pptx_data)?;
125 Ok(())
126}
127
128fn create_data_table_example() -> Result<(), Box<dyn std::error::Error>> {
129 let header_cells = vec![
130 TableCell::new("Product").bold().background_color("1F497D"),
131 TableCell::new("Revenue").bold().background_color("1F497D"),
132 TableCell::new("Growth").bold().background_color("1F497D"),
133 ];
134 let header_row = TableRow::new(header_cells);
135
136 let data_rows = vec![
137 TableRow::new(vec![
138 TableCell::new("Product A"),
139 TableCell::new("$100K"),
140 TableCell::new("+15%"),
141 ]),
142 TableRow::new(vec![
143 TableCell::new("Product B"),
144 TableCell::new("$150K"),
145 TableCell::new("+22%"),
146 ]),
147 TableRow::new(vec![
148 TableCell::new("Product C"),
149 TableCell::new("$200K"),
150 TableCell::new("+18%"),
151 ]),
152 ];
153
154 let table = Table::new(
155 vec![vec![header_row], data_rows].concat(),
156 vec![2000000, 2000000, 1500000],
157 457200,
158 1400000,
159 );
160
161 let slides = vec![
162 SlideContent::new("Sales Data Table")
163 .title_bold(true)
164 .title_size(48)
165 .add_bullet("Quarterly sales figures"),
166 SlideContent::new("Q1 2025 Sales")
167 .table(table),
168 SlideContent::new("Summary")
169 .content_bold(true)
170 .add_bullet("Total Revenue: $450K")
171 .add_bullet("Average Growth: +18.3%")
172 .add_bullet("Best Performer: Product C"),
173 ];
174
175 let pptx_data = create_pptx_with_content("Sales Data", slides)?;
176 fs::write("examples/output/data_table.pptx", pptx_data)?;
177 Ok(())
178}
179
180fn create_multiple_tables_example() -> Result<(), Box<dyn std::error::Error>> {
181 // Table 1: Employees
182 let emp_header = TableRow::new(vec![
183 TableCell::new("ID").bold().background_color("4F81BD"),
184 TableCell::new("Name").bold().background_color("4F81BD"),
185 TableCell::new("Department").bold().background_color("4F81BD"),
186 ]);
187 let emp_rows = vec![
188 TableRow::new(vec![
189 TableCell::new("001"),
190 TableCell::new("Alice"),
191 TableCell::new("Engineering"),
192 ]),
193 TableRow::new(vec![
194 TableCell::new("002"),
195 TableCell::new("Bob"),
196 TableCell::new("Sales"),
197 ]),
198 TableRow::new(vec![
199 TableCell::new("003"),
200 TableCell::new("Carol"),
201 TableCell::new("Marketing"),
202 ]),
203 ];
204 let emp_table = Table::new(
205 vec![vec![emp_header], emp_rows].concat(),
206 vec![1000000, 2000000, 2000000],
207 500000,
208 1500000,
209 );
210
211 // Table 2: Projects
212 let proj_header = TableRow::new(vec![
213 TableCell::new("Project").bold().background_color("003366"),
214 TableCell::new("Status").bold().background_color("003366"),
215 TableCell::new("Owner").bold().background_color("003366"),
216 ]);
217 let proj_rows = vec![
218 TableRow::new(vec![
219 TableCell::new("Project A"),
220 TableCell::new("In Progress"),
221 TableCell::new("Alice"),
222 ]),
223 TableRow::new(vec![
224 TableCell::new("Project B"),
225 TableCell::new("Completed"),
226 TableCell::new("Bob"),
227 ]),
228 TableRow::new(vec![
229 TableCell::new("Project C"),
230 TableCell::new("Planning"),
231 TableCell::new("Carol"),
232 ]),
233 ];
234 let proj_table = Table::new(
235 vec![vec![proj_header], proj_rows].concat(),
236 vec![2000000, 2000000, 1500000],
237 500000,
238 1500000,
239 );
240
241 let slides = vec![
242 SlideContent::new("Multiple Tables")
243 .title_bold(true)
244 .add_bullet("Slide with multiple tables"),
245 SlideContent::new("Table 1: Employees")
246 .table(emp_table),
247 SlideContent::new("Table 2: Projects")
248 .table(proj_table),
249 SlideContent::new("Summary")
250 .add_bullet("Total Employees: 3")
251 .add_bullet("Active Projects: 3")
252 .add_bullet("Completion Rate: 33%"),
253 ];
254
255 let pptx_data = create_pptx_with_content("Multiple Tables", slides)?;
256 fs::write("examples/output/multiple_tables.pptx", pptx_data)?;
257 Ok(())
258}
259
260/// Helper function to demonstrate table creation
261#[allow(dead_code)]
262fn create_table_structure() -> Table {
263 // Create table using builder
264 TableBuilder::new(vec![1000000, 1000000, 1000000])
265 .position(500000, 1000000)
266 .add_simple_row(vec!["Header 1", "Header 2", "Header 3"])
267 .add_simple_row(vec!["Data 1", "Data 2", "Data 3"])
268 .add_simple_row(vec!["Data 4", "Data 5", "Data 6"])
269 .build()
270}
271
272/// Helper function to demonstrate styled table
273#[allow(dead_code)]
274fn create_styled_table() -> Table {
275 let header_cells = vec![
276 TableCell::new("Name").bold().background_color("003366"),
277 TableCell::new("Age").bold().background_color("003366"),
278 TableCell::new("City").bold().background_color("003366"),
279 ];
280 let header_row = TableRow::new(header_cells);
281
282 let data_cells = vec![
283 TableCell::new("Alice"),
284 TableCell::new("30"),
285 TableCell::new("NYC"),
286 ];
287 let data_row = TableRow::new(data_cells);
288
289 Table::new(
290 vec![header_row, data_row],
291 vec![1000000, 1000000, 1000000],
292 500000,
293 1000000,
294 )
295}33fn create_text_formatting_table() -> Table {
34 let header_cells = vec![
35 TableCell::new("Style").bold().background_color("4F81BD"),
36 TableCell::new("Example").bold().background_color("4F81BD"),
37 TableCell::new("Description").bold().background_color("4F81BD"),
38 ];
39 let header_row = TableRow::new(header_cells);
40
41 let rows = vec![
42 TableRow::new(vec![
43 TableCell::new("Bold"),
44 TableCell::new("Bold Text").bold(),
45 TableCell::new("Text with bold formatting"),
46 ]),
47 TableRow::new(vec![
48 TableCell::new("Italic"),
49 TableCell::new("Italic Text").italic(),
50 TableCell::new("Text with italic formatting"),
51 ]),
52 TableRow::new(vec![
53 TableCell::new("Underline"),
54 TableCell::new("Underlined Text").underline(),
55 TableCell::new("Text with underline formatting"),
56 ]),
57 TableRow::new(vec![
58 TableCell::new("Bold + Italic"),
59 TableCell::new("Bold Italic Text").bold().italic(),
60 TableCell::new("Text with both bold and italic"),
61 ]),
62 TableRow::new(vec![
63 TableCell::new("All Three"),
64 TableCell::new("Bold Italic Underlined").bold().italic().underline(),
65 TableCell::new("Text with all formatting options"),
66 ]),
67 ];
68
69 Table::new(
70 vec![vec![header_row], rows].concat(),
71 vec![2000000, 3000000, 3000000],
72 500000,
73 1500000,
74 )
75}
76
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn italic(self) -> Self
pub fn italic(self) -> Self
Set cell text as italic
Examples found in repository?
33fn create_text_formatting_table() -> Table {
34 let header_cells = vec![
35 TableCell::new("Style").bold().background_color("4F81BD"),
36 TableCell::new("Example").bold().background_color("4F81BD"),
37 TableCell::new("Description").bold().background_color("4F81BD"),
38 ];
39 let header_row = TableRow::new(header_cells);
40
41 let rows = vec![
42 TableRow::new(vec![
43 TableCell::new("Bold"),
44 TableCell::new("Bold Text").bold(),
45 TableCell::new("Text with bold formatting"),
46 ]),
47 TableRow::new(vec![
48 TableCell::new("Italic"),
49 TableCell::new("Italic Text").italic(),
50 TableCell::new("Text with italic formatting"),
51 ]),
52 TableRow::new(vec![
53 TableCell::new("Underline"),
54 TableCell::new("Underlined Text").underline(),
55 TableCell::new("Text with underline formatting"),
56 ]),
57 TableRow::new(vec![
58 TableCell::new("Bold + Italic"),
59 TableCell::new("Bold Italic Text").bold().italic(),
60 TableCell::new("Text with both bold and italic"),
61 ]),
62 TableRow::new(vec![
63 TableCell::new("All Three"),
64 TableCell::new("Bold Italic Underlined").bold().italic().underline(),
65 TableCell::new("Text with all formatting options"),
66 ]),
67 ];
68
69 Table::new(
70 vec![vec![header_row], rows].concat(),
71 vec![2000000, 3000000, 3000000],
72 500000,
73 1500000,
74 )
75}
76
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}Sourcepub fn underline(self) -> Self
pub fn underline(self) -> Self
Set cell text as underlined
Examples found in repository?
33fn create_text_formatting_table() -> Table {
34 let header_cells = vec![
35 TableCell::new("Style").bold().background_color("4F81BD"),
36 TableCell::new("Example").bold().background_color("4F81BD"),
37 TableCell::new("Description").bold().background_color("4F81BD"),
38 ];
39 let header_row = TableRow::new(header_cells);
40
41 let rows = vec![
42 TableRow::new(vec![
43 TableCell::new("Bold"),
44 TableCell::new("Bold Text").bold(),
45 TableCell::new("Text with bold formatting"),
46 ]),
47 TableRow::new(vec![
48 TableCell::new("Italic"),
49 TableCell::new("Italic Text").italic(),
50 TableCell::new("Text with italic formatting"),
51 ]),
52 TableRow::new(vec![
53 TableCell::new("Underline"),
54 TableCell::new("Underlined Text").underline(),
55 TableCell::new("Text with underline formatting"),
56 ]),
57 TableRow::new(vec![
58 TableCell::new("Bold + Italic"),
59 TableCell::new("Bold Italic Text").bold().italic(),
60 TableCell::new("Text with both bold and italic"),
61 ]),
62 TableRow::new(vec![
63 TableCell::new("All Three"),
64 TableCell::new("Bold Italic Underlined").bold().italic().underline(),
65 TableCell::new("Text with all formatting options"),
66 ]),
67 ];
68
69 Table::new(
70 vec![vec![header_row], rows].concat(),
71 vec![2000000, 3000000, 3000000],
72 500000,
73 1500000,
74 )
75}
76
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}Sourcepub fn text_color(self, color: &str) -> Self
pub fn text_color(self, color: &str) -> Self
Set cell text color (RGB hex format, e.g., “FF0000” or “#FF0000”)
Examples found in repository?
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}More examples
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn background_color(self, color: &str) -> Self
pub fn background_color(self, color: &str) -> Self
Set cell background color (RGB hex format, e.g., “FF0000” or “#FF0000”)
Examples found in repository?
29fn create_employee_table() -> Table {
30 let header_cells = vec![
31 TableCell::new("Name").bold().background_color("4F81BD"),
32 TableCell::new("Department").bold().background_color("4F81BD"),
33 TableCell::new("Status").bold().background_color("4F81BD"),
34 ];
35 let header_row = TableRow::new(header_cells);
36
37 let rows = vec![
38 TableRow::new(vec![
39 TableCell::new("Alice Johnson"),
40 TableCell::new("Engineering"),
41 TableCell::new("Active"),
42 ]),
43 TableRow::new(vec![
44 TableCell::new("Bob Smith"),
45 TableCell::new("Sales"),
46 TableCell::new("Active"),
47 ]),
48 TableRow::new(vec![
49 TableCell::new("Carol Davis"),
50 TableCell::new("Marketing"),
51 TableCell::new("On Leave"),
52 ]),
53 TableRow::new(vec![
54 TableCell::new("David Wilson"),
55 TableCell::new("Engineering"),
56 TableCell::new("Active"),
57 ]),
58 TableRow::new(vec![
59 TableCell::new("Emma Brown"),
60 TableCell::new("HR"),
61 TableCell::new("Active"),
62 ]),
63 ];
64
65 Table::new(
66 vec![vec![header_row], rows].concat(),
67 vec![2000000, 2500000, 1500000],
68 500000,
69 1500000,
70 )
71}
72
73fn create_sales_table() -> Table {
74 let header_cells = vec![
75 TableCell::new("Product").bold().background_color("003366"),
76 TableCell::new("Revenue").bold().background_color("003366"),
77 TableCell::new("Growth").bold().background_color("003366"),
78 ];
79 let header_row = TableRow::new(header_cells);
80
81 let rows = vec![
82 TableRow::new(vec![
83 TableCell::new("Cloud Services"),
84 TableCell::new("$450K"),
85 TableCell::new("+28%"),
86 ]),
87 TableRow::new(vec![
88 TableCell::new("Enterprise Suite"),
89 TableCell::new("$320K"),
90 TableCell::new("+15%"),
91 ]),
92 TableRow::new(vec![
93 TableCell::new("Developer Tools"),
94 TableCell::new("$280K"),
95 TableCell::new("+42%"),
96 ]),
97 TableRow::new(vec![
98 TableCell::new("Mobile App"),
99 TableCell::new("$195K"),
100 TableCell::new("+35%"),
101 ]),
102 TableRow::new(vec![
103 TableCell::new("Support Services"),
104 TableCell::new("$155K"),
105 TableCell::new("+12%"),
106 ]),
107 ];
108
109 Table::new(
110 vec![vec![header_row], rows].concat(),
111 vec![2200000, 2000000, 1800000],
112 500000,
113 1500000,
114 )
115}
116
117fn create_quarterly_table() -> Table {
118 let header_cells = vec![
119 TableCell::new("Quarter").bold().background_color("1F497D"),
120 TableCell::new("Revenue").bold().background_color("1F497D"),
121 TableCell::new("Profit").bold().background_color("1F497D"),
122 ];
123 let header_row = TableRow::new(header_cells);
124
125 let q1_cells = vec![
126 TableCell::new("Q1 2025"),
127 TableCell::new("$450K"),
128 TableCell::new("$90K"),
129 ];
130 let q1 = TableRow::new(q1_cells);
131
132 let q2_cells = vec![
133 TableCell::new("Q2 2025"),
134 TableCell::new("$520K"),
135 TableCell::new("$110K"),
136 ];
137 let q2 = TableRow::new(q2_cells);
138
139 let q3_cells = vec![
140 TableCell::new("Q3 2025"),
141 TableCell::new("$580K"),
142 TableCell::new("$130K"),
143 ];
144 let q3 = TableRow::new(q3_cells);
145
146 Table::new(
147 vec![header_row, q1, q2, q3],
148 vec![2000000, 2000000, 2000000],
149 500000,
150 1500000,
151 )
152}More examples
81fn create_styled_table_example() -> Result<(), Box<dyn std::error::Error>> {
82 let header_cells = vec![
83 TableCell::new("Name").bold().background_color("003366"),
84 TableCell::new("Age").bold().background_color("003366"),
85 TableCell::new("City").bold().background_color("003366"),
86 ];
87 let header_row = TableRow::new(header_cells);
88
89 let data_rows = vec![
90 TableRow::new(vec![
91 TableCell::new("Alice"),
92 TableCell::new("30"),
93 TableCell::new("NYC"),
94 ]),
95 TableRow::new(vec![
96 TableCell::new("Bob"),
97 TableCell::new("28"),
98 TableCell::new("LA"),
99 ]),
100 TableRow::new(vec![
101 TableCell::new("Carol"),
102 TableCell::new("35"),
103 TableCell::new("Chicago"),
104 ]),
105 ];
106
107 let table = Table::new(
108 vec![vec![header_row], data_rows].concat(),
109 vec![1500000, 1500000, 1500000],
110 500000,
111 1500000,
112 );
113
114 let slides = vec![
115 SlideContent::new("Styled Table")
116 .title_bold(true)
117 .title_color("003366")
118 .add_bullet("Table with formatting"),
119 SlideContent::new("People Data")
120 .table(table),
121 ];
122
123 let pptx_data = create_pptx_with_content("Styled Table", slides)?;
124 fs::write("examples/output/styled_table.pptx", pptx_data)?;
125 Ok(())
126}
127
128fn create_data_table_example() -> Result<(), Box<dyn std::error::Error>> {
129 let header_cells = vec![
130 TableCell::new("Product").bold().background_color("1F497D"),
131 TableCell::new("Revenue").bold().background_color("1F497D"),
132 TableCell::new("Growth").bold().background_color("1F497D"),
133 ];
134 let header_row = TableRow::new(header_cells);
135
136 let data_rows = vec![
137 TableRow::new(vec![
138 TableCell::new("Product A"),
139 TableCell::new("$100K"),
140 TableCell::new("+15%"),
141 ]),
142 TableRow::new(vec![
143 TableCell::new("Product B"),
144 TableCell::new("$150K"),
145 TableCell::new("+22%"),
146 ]),
147 TableRow::new(vec![
148 TableCell::new("Product C"),
149 TableCell::new("$200K"),
150 TableCell::new("+18%"),
151 ]),
152 ];
153
154 let table = Table::new(
155 vec![vec![header_row], data_rows].concat(),
156 vec![2000000, 2000000, 1500000],
157 457200,
158 1400000,
159 );
160
161 let slides = vec![
162 SlideContent::new("Sales Data Table")
163 .title_bold(true)
164 .title_size(48)
165 .add_bullet("Quarterly sales figures"),
166 SlideContent::new("Q1 2025 Sales")
167 .table(table),
168 SlideContent::new("Summary")
169 .content_bold(true)
170 .add_bullet("Total Revenue: $450K")
171 .add_bullet("Average Growth: +18.3%")
172 .add_bullet("Best Performer: Product C"),
173 ];
174
175 let pptx_data = create_pptx_with_content("Sales Data", slides)?;
176 fs::write("examples/output/data_table.pptx", pptx_data)?;
177 Ok(())
178}
179
180fn create_multiple_tables_example() -> Result<(), Box<dyn std::error::Error>> {
181 // Table 1: Employees
182 let emp_header = TableRow::new(vec![
183 TableCell::new("ID").bold().background_color("4F81BD"),
184 TableCell::new("Name").bold().background_color("4F81BD"),
185 TableCell::new("Department").bold().background_color("4F81BD"),
186 ]);
187 let emp_rows = vec![
188 TableRow::new(vec![
189 TableCell::new("001"),
190 TableCell::new("Alice"),
191 TableCell::new("Engineering"),
192 ]),
193 TableRow::new(vec![
194 TableCell::new("002"),
195 TableCell::new("Bob"),
196 TableCell::new("Sales"),
197 ]),
198 TableRow::new(vec![
199 TableCell::new("003"),
200 TableCell::new("Carol"),
201 TableCell::new("Marketing"),
202 ]),
203 ];
204 let emp_table = Table::new(
205 vec![vec![emp_header], emp_rows].concat(),
206 vec![1000000, 2000000, 2000000],
207 500000,
208 1500000,
209 );
210
211 // Table 2: Projects
212 let proj_header = TableRow::new(vec![
213 TableCell::new("Project").bold().background_color("003366"),
214 TableCell::new("Status").bold().background_color("003366"),
215 TableCell::new("Owner").bold().background_color("003366"),
216 ]);
217 let proj_rows = vec![
218 TableRow::new(vec![
219 TableCell::new("Project A"),
220 TableCell::new("In Progress"),
221 TableCell::new("Alice"),
222 ]),
223 TableRow::new(vec![
224 TableCell::new("Project B"),
225 TableCell::new("Completed"),
226 TableCell::new("Bob"),
227 ]),
228 TableRow::new(vec![
229 TableCell::new("Project C"),
230 TableCell::new("Planning"),
231 TableCell::new("Carol"),
232 ]),
233 ];
234 let proj_table = Table::new(
235 vec![vec![proj_header], proj_rows].concat(),
236 vec![2000000, 2000000, 1500000],
237 500000,
238 1500000,
239 );
240
241 let slides = vec![
242 SlideContent::new("Multiple Tables")
243 .title_bold(true)
244 .add_bullet("Slide with multiple tables"),
245 SlideContent::new("Table 1: Employees")
246 .table(emp_table),
247 SlideContent::new("Table 2: Projects")
248 .table(proj_table),
249 SlideContent::new("Summary")
250 .add_bullet("Total Employees: 3")
251 .add_bullet("Active Projects: 3")
252 .add_bullet("Completion Rate: 33%"),
253 ];
254
255 let pptx_data = create_pptx_with_content("Multiple Tables", slides)?;
256 fs::write("examples/output/multiple_tables.pptx", pptx_data)?;
257 Ok(())
258}
259
260/// Helper function to demonstrate table creation
261#[allow(dead_code)]
262fn create_table_structure() -> Table {
263 // Create table using builder
264 TableBuilder::new(vec![1000000, 1000000, 1000000])
265 .position(500000, 1000000)
266 .add_simple_row(vec!["Header 1", "Header 2", "Header 3"])
267 .add_simple_row(vec!["Data 1", "Data 2", "Data 3"])
268 .add_simple_row(vec!["Data 4", "Data 5", "Data 6"])
269 .build()
270}
271
272/// Helper function to demonstrate styled table
273#[allow(dead_code)]
274fn create_styled_table() -> Table {
275 let header_cells = vec![
276 TableCell::new("Name").bold().background_color("003366"),
277 TableCell::new("Age").bold().background_color("003366"),
278 TableCell::new("City").bold().background_color("003366"),
279 ];
280 let header_row = TableRow::new(header_cells);
281
282 let data_cells = vec![
283 TableCell::new("Alice"),
284 TableCell::new("30"),
285 TableCell::new("NYC"),
286 ];
287 let data_row = TableRow::new(data_cells);
288
289 Table::new(
290 vec![header_row, data_row],
291 vec![1000000, 1000000, 1000000],
292 500000,
293 1000000,
294 )
295}33fn create_text_formatting_table() -> Table {
34 let header_cells = vec![
35 TableCell::new("Style").bold().background_color("4F81BD"),
36 TableCell::new("Example").bold().background_color("4F81BD"),
37 TableCell::new("Description").bold().background_color("4F81BD"),
38 ];
39 let header_row = TableRow::new(header_cells);
40
41 let rows = vec![
42 TableRow::new(vec![
43 TableCell::new("Bold"),
44 TableCell::new("Bold Text").bold(),
45 TableCell::new("Text with bold formatting"),
46 ]),
47 TableRow::new(vec![
48 TableCell::new("Italic"),
49 TableCell::new("Italic Text").italic(),
50 TableCell::new("Text with italic formatting"),
51 ]),
52 TableRow::new(vec![
53 TableCell::new("Underline"),
54 TableCell::new("Underlined Text").underline(),
55 TableCell::new("Text with underline formatting"),
56 ]),
57 TableRow::new(vec![
58 TableCell::new("Bold + Italic"),
59 TableCell::new("Bold Italic Text").bold().italic(),
60 TableCell::new("Text with both bold and italic"),
61 ]),
62 TableRow::new(vec![
63 TableCell::new("All Three"),
64 TableCell::new("Bold Italic Underlined").bold().italic().underline(),
65 TableCell::new("Text with all formatting options"),
66 ]),
67 ];
68
69 Table::new(
70 vec![vec![header_row], rows].concat(),
71 vec![2000000, 3000000, 3000000],
72 500000,
73 1500000,
74 )
75}
76
77fn create_color_table() -> Table {
78 let header_cells = vec![
79 TableCell::new("Text Color").bold().background_color("1F497D"),
80 TableCell::new("Background").bold().background_color("1F497D"),
81 TableCell::new("Example").bold().background_color("1F497D"),
82 ];
83 let header_row = TableRow::new(header_cells);
84
85 let rows = vec![
86 TableRow::new(vec![
87 TableCell::new("Red"),
88 TableCell::new("White"),
89 TableCell::new("Red Text").text_color("FF0000").background_color("FFFFFF"),
90 ]),
91 TableRow::new(vec![
92 TableCell::new("Blue"),
93 TableCell::new("Yellow"),
94 TableCell::new("Blue Text").text_color("0000FF").background_color("FFFF00"),
95 ]),
96 TableRow::new(vec![
97 TableCell::new("Green"),
98 TableCell::new("Light Gray"),
99 TableCell::new("Green Text").text_color("00FF00").background_color("E0E0E0"),
100 ]),
101 TableRow::new(vec![
102 TableCell::new("Purple"),
103 TableCell::new("White"),
104 TableCell::new("Purple Text").text_color("800080").background_color("FFFFFF"),
105 ]),
106 ];
107
108 Table::new(
109 vec![vec![header_row], rows].concat(),
110 vec![2000000, 2000000, 4000000],
111 500000,
112 1500000,
113 )
114}
115
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn font_size(self, size: u32) -> Self
pub fn font_size(self, size: u32) -> Self
Set font size in points
Examples found in repository?
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}More examples
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn font_family(self, family: &str) -> Self
pub fn font_family(self, family: &str) -> Self
Set font family name
Examples found in repository?
116fn create_font_table() -> Table {
117 let header_cells = vec![
118 TableCell::new("Font Size").bold().background_color("366092"),
119 TableCell::new("Font Family").bold().background_color("366092"),
120 TableCell::new("Example").bold().background_color("366092"),
121 ];
122 let header_row = TableRow::new(header_cells);
123
124 let rows = vec![
125 TableRow::new(vec![
126 TableCell::new("12pt"),
127 TableCell::new("Arial"),
128 TableCell::new("Small Arial Text").font_size(12).font_family("Arial"),
129 ]),
130 TableRow::new(vec![
131 TableCell::new("18pt"),
132 TableCell::new("Calibri"),
133 TableCell::new("Medium Calibri Text").font_size(18).font_family("Calibri"),
134 ]),
135 TableRow::new(vec![
136 TableCell::new("24pt"),
137 TableCell::new("Times New Roman"),
138 TableCell::new("Large Times Text").font_size(24).font_family("Times New Roman"),
139 ]),
140 TableRow::new(vec![
141 TableCell::new("32pt"),
142 TableCell::new("Arial"),
143 TableCell::new("Extra Large Arial").font_size(32).font_family("Arial"),
144 ]),
145 ];
146
147 Table::new(
148 vec![vec![header_row], rows].concat(),
149 vec![2000000, 2500000, 3500000],
150 500000,
151 1500000,
152 )
153}
154
155fn create_combined_table() -> Table {
156 let header_cells = vec![
157 TableCell::new("Feature").bold().background_color("C0504D"),
158 TableCell::new("Styled Example").bold().background_color("C0504D"),
159 ];
160 let header_row = TableRow::new(header_cells);
161
162 let rows = vec![
163 TableRow::new(vec![
164 TableCell::new("Important Header"),
165 TableCell::new("Critical Data")
166 .bold()
167 .text_color("FFFFFF")
168 .background_color("C0504D")
169 .font_size(20),
170 ]),
171 TableRow::new(vec![
172 TableCell::new("Emphasis"),
173 TableCell::new("Highlighted Text")
174 .bold()
175 .italic()
176 .text_color("0000FF")
177 .font_size(18)
178 .font_family("Calibri"),
179 ]),
180 TableRow::new(vec![
181 TableCell::new("Warning"),
182 TableCell::new("Warning Message")
183 .bold()
184 .underline()
185 .text_color("FF6600")
186 .background_color("FFF4E6")
187 .font_size(16),
188 ]),
189 TableRow::new(vec![
190 TableCell::new("Success"),
191 TableCell::new("Success Indicator")
192 .bold()
193 .text_color("00AA00")
194 .background_color("E6F7E6")
195 .font_size(18)
196 .font_family("Arial"),
197 ]),
198 ];
199
200 Table::new(
201 vec![vec![header_row], rows].concat(),
202 vec![3000000, 5000000],
203 500000,
204 1500000,
205 )
206}Sourcepub fn align_left(self) -> Self
pub fn align_left(self) -> Self
Set horizontal text alignment to left
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn align_right(self) -> Self
pub fn align_right(self) -> Self
Set horizontal text alignment to right
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn align_center(self) -> Self
pub fn align_center(self) -> Self
Set horizontal text alignment to center
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn valign(self, valign: CellVAlign) -> Self
pub fn valign(self, valign: CellVAlign) -> Self
Set vertical text alignment
Sourcepub fn valign_top(self) -> Self
pub fn valign_top(self) -> Self
Set vertical text alignment to top
Sourcepub fn valign_bottom(self) -> Self
pub fn valign_bottom(self) -> Self
Set vertical text alignment to bottom
Sourcepub fn grid_span(self, span: u32) -> Self
pub fn grid_span(self, span: u32) -> Self
Set horizontal span (gridSpan) - this cell covers multiple columns
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn row_span(self, span: u32) -> Self
pub fn row_span(self, span: u32) -> Self
Set vertical span (rowSpan) - this cell covers multiple rows
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn h_merge(self) -> Self
pub fn h_merge(self) -> Self
Mark this cell as horizontally merged (covered by another cell’s gridSpan)
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn v_merge(self) -> Self
pub fn v_merge(self) -> Self
Mark this cell as vertically merged (covered by another cell’s rowSpan)
Examples found in repository?
84fn main() -> Result<(), Box<dyn std::error::Error>> {
85 println!("╔══════════════════════════════════════════════════════════════╗");
86 println!("║ PPTX-RS Element Showcase - Complete Coverage ║");
87 println!("╚══════════════════════════════════════════════════════════════╝\n");
88
89 let mut slides = Vec::new();
90
91 // =========================================================================
92 // SLIDE 1: CenteredTitle Layout + Title Formatting
93 // =========================================================================
94 println!("📐 Slide 1: CenteredTitle Layout + Title Formatting");
95 slides.push(
96 SlideContent::new("PPTX-RS Element Showcase")
97 .layout(SlideLayout::CenteredTitle)
98 .title_size(54)
99 .title_bold(true)
100 .title_color("1F497D"),
101 );
102
103 // =========================================================================
104 // SLIDE 2: TitleOnly Layout
105 // =========================================================================
106 println!("📐 Slide 2: TitleOnly Layout");
107 slides.push(
108 SlideContent::new("Section: Slide Layouts")
109 .layout(SlideLayout::TitleOnly)
110 .title_size(48)
111 .title_bold(true)
112 .title_color("C0504D"),
113 );
114
115 // =========================================================================
116 // SLIDE 3: TitleAndContent Layout + All Text Formatting
117 // =========================================================================
118 println!("📝 Slide 3: TitleAndContent + Text Formatting");
119 slides.push(
120 SlideContent::new("Text Formatting Options")
121 .layout(SlideLayout::TitleAndContent)
122 .title_color("1F497D")
123 .title_bold(true)
124 .title_italic(true)
125 .title_underline(true)
126 .title_size(44)
127 .add_bullet("Normal text (default)")
128 .add_bullet("Bold content text")
129 .add_bullet("Italic content text")
130 .add_bullet("Underlined content")
131 .add_bullet("Custom font size (28pt)")
132 .add_bullet("Custom color (#4F81BD)")
133 .content_bold(true)
134 .content_italic(true)
135 .content_underline(true)
136 .content_size(28)
137 .content_color("4F81BD"),
138 );
139
140 // =========================================================================
141 // SLIDE 4: TitleAndBigContent Layout
142 // =========================================================================
143 println!("📐 Slide 4: TitleAndBigContent Layout");
144 slides.push(
145 SlideContent::new("Key Highlights")
146 .layout(SlideLayout::TitleAndBigContent)
147 .title_color("1F497D")
148 .add_bullet("Large content area for emphasis")
149 .add_bullet("Perfect for key messages")
150 .add_bullet("Smaller title, bigger content")
151 .content_bold(true)
152 .content_size(32),
153 );
154
155 // =========================================================================
156 // SLIDE 5: TwoColumn Layout
157 // =========================================================================
158 println!("📐 Slide 5: TwoColumn Layout");
159 slides.push(
160 SlideContent::new("Two Column Comparison")
161 .layout(SlideLayout::TwoColumn)
162 .title_color("1F497D")
163 .add_bullet("Left Column Item 1")
164 .add_bullet("Left Column Item 2")
165 .add_bullet("Left Column Item 3")
166 .add_bullet("Right Column Item 1")
167 .add_bullet("Right Column Item 2")
168 .add_bullet("Right Column Item 3")
169 .content_size(24),
170 );
171
172 // =========================================================================
173 // SLIDE 6: Blank Layout
174 // =========================================================================
175 println!("📐 Slide 6: Blank Layout");
176 slides.push(SlideContent::new("").layout(SlideLayout::Blank));
177
178 // =========================================================================
179 // SLIDE 7: Table with All Cell Styling Options
180 // =========================================================================
181 println!("📊 Slide 7: Table with Cell Styling");
182 let styled_table = TableBuilder::new(vec![1500000, 1500000, 1500000])
183 .add_row(TableRow::new(vec![
184 TableCell::new("Header 1").bold().background_color("1F497D"),
185 TableCell::new("Header 2").bold().background_color("4F81BD"),
186 TableCell::new("Header 3").bold().background_color("8064A2"),
187 ]))
188 .add_row(TableRow::new(vec![
189 TableCell::new("Bold Cell").bold(),
190 TableCell::new("Normal Cell"),
191 TableCell::new("Colored").background_color("9BBB59"),
192 ]))
193 .add_row(TableRow::new(vec![
194 TableCell::new("Red BG").background_color("C0504D"),
195 TableCell::new("Green BG").background_color("9BBB59"),
196 TableCell::new("Blue BG").background_color("4F81BD"),
197 ]))
198 .add_row(TableRow::new(vec![
199 TableCell::new("Row 3 Col 1"),
200 TableCell::new("Row 3 Col 2"),
201 TableCell::new("Row 3 Col 3")
202 .bold()
203 .background_color("F79646"),
204 ]))
205 .position(500000, 1800000)
206 .build();
207
208 slides.push(
209 SlideContent::new("Table with Cell Styling")
210 .table(styled_table)
211 .title_color("1F497D"),
212 );
213
214 // =========================================================================
215 // SLIDE 8: Charts (Bar, Line, Pie)
216 // =========================================================================
217 println!("📈 Slide 8: Chart Types");
218
219 // Create chart data structures (for demonstration)
220 let _bar_chart = ChartBuilder::new("Sales by Region", ChartType::Bar)
221 .categories(vec!["North", "South", "East", "West"])
222 .add_series(ChartSeries::new("2023", vec![100.0, 80.0, 120.0, 90.0]))
223 .add_series(ChartSeries::new("2024", vec![120.0, 95.0, 140.0, 110.0]))
224 .build();
225
226 let _line_chart = ChartBuilder::new("Monthly Trend", ChartType::Line)
227 .categories(vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun"])
228 .add_series(ChartSeries::new(
229 "Revenue",
230 vec![10.0, 12.0, 15.0, 14.0, 18.0, 22.0],
231 ))
232 .build();
233
234 let _pie_chart = ChartBuilder::new("Market Share", ChartType::Pie)
235 .categories(vec!["Product A", "Product B", "Product C", "Others"])
236 .add_series(ChartSeries::new("Share", vec![40.0, 30.0, 20.0, 10.0]))
237 .build();
238
239 slides.push(
240 SlideContent::new("Chart Types: Bar, Line, Pie")
241 .with_chart()
242 .title_color("1F497D")
243 .add_bullet("Bar Chart: Compare categories")
244 .add_bullet("Line Chart: Show trends over time")
245 .add_bullet("Pie Chart: Show proportions")
246 .content_size(24),
247 );
248
249 // =========================================================================
250 // SLIDE 9: Shapes with Different Fills
251 // =========================================================================
252 println!("🔷 Slide 9: Shapes with Fills");
253
254 let rect_shape = rect(0.5, 1.75, 2.2, 1.1)
255 .fill(hex("4F81BD"))
256 .text("Rectangle");
257
258 let ellipse_shape = ellipse(3.3, 1.75, 2.2, 1.1)
259 .fill(hex("9BBB59"))
260 .text("Ellipse");
261
262 let rounded = rounded_rect(6.0, 1.75, 2.2, 1.1)
263 .fill(hex("C0504D"))
264 .text("Rounded");
265
266 let triangle_shape = triangle(1.6, 3.3, 1.6, 1.3)
267 .fill(hex("8064A2"))
268 .text("Triangle");
269
270 let diamond_shape = diamond(4.4, 3.3, 1.6, 1.3)
271 .fill(hex("F79646"))
272 .text("Diamond");
273
274 slides.push(
275 SlideContent::new("Shape Types with Color Fills")
276 .add_shape(rect_shape)
277 .add_shape(ellipse_shape)
278 .add_shape(rounded)
279 .add_shape(triangle_shape)
280 .add_shape(diamond_shape)
281 .title_color("1F497D"),
282 );
283
284 // =========================================================================
285 // SLIDE 10: Gradient Fills (NEW)
286 // =========================================================================
287 println!("🌈 Slide 10: Gradient Fills");
288
289 // Horizontal gradient
290 let gradient_h = rect(0.5, 1.75, 2.7, 1.3)
291 .with_gradient(GradientFill::linear(
292 "1565C0",
293 "42A5F5",
294 GradientDirection::Horizontal,
295 ))
296 .text("Horizontal");
297
298 // Vertical gradient
299 let gradient_v = rect(3.5, 1.75, 2.7, 1.3)
300 .with_gradient(GradientFill::linear(
301 "2E7D32",
302 "81C784",
303 GradientDirection::Vertical,
304 ))
305 .text("Vertical");
306
307 // Diagonal gradient
308 let gradient_d = rounded_rect(6.5, 1.75, 2.7, 1.3)
309 .with_gradient(GradientFill::linear(
310 "C62828",
311 "EF9A9A",
312 GradientDirection::DiagonalDown,
313 ))
314 .text("Diagonal");
315
316 // Three-color gradient
317 let gradient_3 = ellipse(2.0, 3.5, 2.7, 1.3)
318 .with_gradient(GradientFill::three_color(
319 "FF6F00",
320 "FFC107",
321 "FFEB3B",
322 GradientDirection::Horizontal,
323 ))
324 .text("3-Color");
325
326 // Custom angle gradient
327 let gradient_angle = rounded_rect(5.2, 3.5, 2.7, 1.3)
328 .with_gradient(GradientFill::linear(
329 "7B1FA2",
330 "E1BEE7",
331 GradientDirection::Angle(135),
332 ))
333 .text("135° Angle");
334
335 slides.push(
336 SlideContent::new("Gradient Fills - Multiple Directions")
337 .add_shape(gradient_h)
338 .add_shape(gradient_v)
339 .add_shape(gradient_d)
340 .add_shape(gradient_3)
341 .add_shape(gradient_angle)
342 .title_color("1F497D"),
343 );
344
345 // =========================================================================
346 // SLIDE 11: Transparency (NEW)
347 // =========================================================================
348 println!("👻 Slide 11: Transparency Effects");
349
350 // Base shape (fully opaque)
351 let base = rect(1.1, 2.0, 3.3, 2.2)
352 .fill(hex("1565C0"))
353 .text("Base (100%)");
354
355 // 25% transparent overlay
356 let trans_25 = rect(2.2, 2.4, 2.7, 1.6)
357 .fill(ColorValue::from_hex("F44336").transparent(25).to_color())
358 .stroke(hex("B71C1C"), 2.0)
359 .text("25% Transparent");
360
361 // 50% transparent overlay
362 let trans_50 = ellipse(4.9, 2.0, 2.7, 2.2)
363 .fill(ColorValue::from_hex("4CAF50").transparent(50).to_color())
364 .stroke(hex("1B5E20"), 2.0)
365 .text("50% Transparent");
366
367 // 75% transparent overlay
368 let trans_75 = rounded_rect(6.0, 2.7, 2.7, 1.6)
369 .fill(ColorValue::from_hex("FF9800").transparent(75).to_color())
370 .stroke(hex("E65100"), 2.0)
371 .text("75% Transparent");
372
373 slides.push(
374 SlideContent::new("Transparency Effects - Overlapping Shapes")
375 .add_shape(base)
376 .add_shape(trans_25)
377 .add_shape(trans_50)
378 .add_shape(trans_75)
379 .title_color("1F497D"),
380 );
381
382 // =========================================================================
383 // SLIDE 12: Styled Connectors (NEW)
384 // =========================================================================
385 println!("🔗 Slide 12: Styled Connectors");
386
387 // Create shapes to connect
388 let box1 = rounded_rect(0.5, 2.0, 2.0, 0.9)
389 .with_id(100)
390 .fill(hex("1565C0"))
391 .text("Start");
392
393 let box2 = rounded_rect(3.8, 2.0, 2.0, 0.9)
394 .with_id(101)
395 .fill(hex("2E7D32"))
396 .text("Process");
397
398 let box3 = rounded_rect(7.1, 2.0, 2.0, 0.9)
399 .with_id(102)
400 .fill(hex("C62828"))
401 .text("End");
402
403 // Straight connector with arrow
404 let conn1 = Connector::straight(2300000, 2200000, 3500000, 2200000)
405 .with_line(ConnectorLine::new("1565C0", 25400))
406 .with_end_arrow(ArrowType::Triangle)
407 .with_arrow_size(ArrowSize::Large);
408
409 // Elbow connector with stealth arrow
410 let conn2 = Connector::elbow(5300000, 2200000, 6500000, 2200000)
411 .with_line(ConnectorLine::new("2E7D32", 38100).with_dash(LineDash::Dash))
412 .with_end_arrow(ArrowType::Stealth)
413 .with_arrow_size(ArrowSize::Medium);
414
415 // Curved connector examples
416 let box4 = ellipse(1.1, 3.5, 1.6, 0.9)
417 .with_id(103)
418 .fill(hex("7B1FA2"))
419 .text("A");
420
421 let box5 = ellipse(4.4, 3.5, 1.6, 0.9)
422 .with_id(104)
423 .fill(hex("00838F"))
424 .text("B");
425
426 let box6 = ellipse(7.7, 3.5, 1.6, 0.9)
427 .with_id(105)
428 .fill(hex("EF6C00"))
429 .text("C");
430
431 // Curved connector with diamond arrow
432 let conn3 = Connector::curved(2500000, 3600000, 4000000, 3600000)
433 .with_line(ConnectorLine::new("7B1FA2", 19050).with_dash(LineDash::DashDot))
434 .with_arrows(ArrowType::Oval, ArrowType::Diamond);
435
436 // Dotted connector
437 let conn4 = Connector::straight(5500000, 3600000, 7000000, 3600000)
438 .with_line(ConnectorLine::new("00838F", 12700).with_dash(LineDash::Dot))
439 .with_end_arrow(ArrowType::Open);
440
441 slides.push(
442 SlideContent::new("Styled Connectors - Types, Arrows, Dashes")
443 .add_shape(box1)
444 .add_shape(box2)
445 .add_shape(box3)
446 .add_shape(box4)
447 .add_shape(box5)
448 .add_shape(box6)
449 .add_connector(conn1)
450 .add_connector(conn2)
451 .add_connector(conn3)
452 .add_connector(conn4)
453 .title_color("1F497D"),
454 );
455
456 // =========================================================================
457 // SLIDE 13: Images with Shadow Effects
458 // =========================================================================
459 println!("🖼️ Slide 13: Images with Shadow Effects");
460
461 // Dynamically load optimized stock photos from assets folder
462 let assets_dir = "examples/assets";
463 let mut stock_photos: Vec<(Vec<u8>, String, String)> = Vec::new();
464
465 // Scan for optimized image files in assets folder
466 if let Ok(entries) = std::fs::read_dir(assets_dir) {
467 let mut files: Vec<_> = entries.flatten().collect();
468 files.sort_by_key(|e| e.file_name());
469
470 for entry in files {
471 if let Some(filename) = entry.file_name().to_str() {
472 // Skip text files
473 if filename.ends_with(".txt") {
474 continue;
475 }
476
477 if let Ok(path) = entry.path().canonicalize() {
478 if let Some(ext) = path.extension() {
479 let ext_str = ext.to_string_lossy().to_lowercase();
480 if ext_str == "jpg" || ext_str == "jpeg" || ext_str == "png" {
481 if let Ok(bytes) = std::fs::read(&path) {
482 let format = if ext_str == "png" { "PNG" } else { "JPEG" };
483 let size_kb = bytes.len() as f64 / 1024.0;
484 stock_photos.push((
485 bytes,
486 format.to_string(),
487 filename.to_string(),
488 ));
489 println!(" Loaded: {} ({:.1} KB)", filename, size_kb);
490 }
491 }
492 }
493 }
494 }
495 }
496 }
497
498 // Use first 3 photos, or repeat if fewer available
499 if stock_photos.is_empty() {
500 panic!("No stock photos found in examples/assets/");
501 }
502 let photo_count = stock_photos.len();
503 let photo1 = &stock_photos[0 % photo_count];
504 let photo2 = &stock_photos[1 % photo_count];
505 let photo3 = &stock_photos[2 % photo_count];
506
507 // SLIDE 13: Shadow Effects
508 let img1_shadow = ImageBuilder::auto(photo1.0.clone())
509 .size(inches(2.2), inches(2.2))
510 .at(inches(0.5), inches(1.6))
511 .shadow()
512 .build();
513 let img2_shadow = ImageBuilder::auto(photo2.0.clone())
514 .size(inches(2.7), inches(2.0))
515 .at(inches(3.5), inches(1.6))
516 .shadow()
517 .build();
518 let img3_shadow = ImageBuilder::auto(photo3.0.clone())
519 .size(inches(2.5), inches(2.0))
520 .at(inches(6.8), inches(1.6))
521 .shadow()
522 .build();
523
524 slides.push(
525 SlideContent::new("Image Effects: Shadow (Outer Shadow)")
526 .add_image(img1_shadow)
527 .add_image(img2_shadow)
528 .add_image(img3_shadow)
529 .title_color("1F497D"),
530 );
531
532 // =========================================================================
533 // SLIDE 14: Images with Reflection Effects
534 // =========================================================================
535 println!("🖼️ Slide 14: Images with Reflection Effects");
536
537 let img1_reflection = ImageBuilder::auto(photo1.0.clone())
538 .size(inches(2.4), inches(2.4))
539 .at(inches(0.9), inches(1.3))
540 .reflection()
541 .build();
542 let img2_reflection = ImageBuilder::auto(photo2.0.clone())
543 .size(inches(3.1), inches(2.2))
544 .at(inches(3.8), inches(1.3))
545 .reflection()
546 .build();
547 let img3_reflection = ImageBuilder::auto(photo3.0.clone())
548 .size(inches(2.6), inches(2.2))
549 .at(inches(7.1), inches(1.3))
550 .reflection()
551 .build();
552
553 slides.push(
554 SlideContent::new("Image Effects: Reflection (Mirror Effect)")
555 .add_image(img1_reflection)
556 .add_image(img2_reflection)
557 .add_image(img3_reflection)
558 .title_color("2E75B5"),
559 );
560
561 // =========================================================================
562 // SLIDE 15: Images with Cropping
563 // =========================================================================
564 println!("🖼️ Slide 15: Images with Cropping");
565
566 let img1_crop = ImageBuilder::auto(photo1.0.clone())
567 .size(inches(2.0), inches(2.0))
568 .at(inches(1.3), inches(2.0))
569 .crop(0.1, 0.1, 0.1, 0.1)
570 .build();
571 let img2_crop = ImageBuilder::auto(photo2.0.clone())
572 .size(inches(3.8), inches(1.6))
573 .at(inches(3.8), inches(2.0))
574 .crop(0.0, 0.2, 0.0, 0.2)
575 .build();
576 let img3_crop = ImageBuilder::auto(photo3.0.clone())
577 .size(inches(2.2), inches(2.2))
578 .at(inches(7.9), inches(2.0))
579 .crop(0.15, 0.0, 0.15, 0.0)
580 .build();
581
582 slides.push(
583 SlideContent::new("Image Cropping: All Sides, Top/Bottom, Left/Right")
584 .add_image(img1_crop)
585 .add_image(img2_crop)
586 .add_image(img3_crop)
587 .title_color("70AD47"),
588 );
589
590 // =========================================================================
591 // SLIDE 16: Images with Glow Effects
592 // =========================================================================
593 println!("🖼️ Slide 16: Images with Glow Effects");
594
595 let img1_glow = ImageBuilder::auto(photo1.0.clone())
596 .size(inches(2.4), inches(2.4))
597 .at(inches(1.0), inches(1.5))
598 .glow()
599 .build();
600 let img2_glow = ImageBuilder::auto(photo2.0.clone())
601 .size(inches(2.9), inches(2.1))
602 .at(inches(4.0), inches(1.5))
603 .glow()
604 .build();
605 let img3_glow = ImageBuilder::auto(photo3.0.clone())
606 .size(inches(2.5), inches(2.1))
607 .at(inches(7.2), inches(1.5))
608 .glow()
609 .build();
610
611 slides.push(
612 SlideContent::new("Image Effects: Glow (Golden Aura)")
613 .add_image(img1_glow)
614 .add_image(img2_glow)
615 .add_image(img3_glow)
616 .title_color("C55A11"),
617 );
618
619 // =========================================================================
620 // SLIDE 17: Images with Soft Edges
621 // =========================================================================
622 println!("🖼️ Slide 17: Images with Soft Edges");
623
624 let img1_soft = ImageBuilder::auto(photo1.0.clone())
625 .size(inches(2.4), inches(2.4))
626 .at(inches(1.0), inches(1.5))
627 .soft_edges()
628 .build();
629 let img2_soft = ImageBuilder::auto(photo2.0.clone())
630 .size(inches(2.9), inches(2.1))
631 .at(inches(4.0), inches(1.5))
632 .soft_edges()
633 .build();
634 let img3_soft = ImageBuilder::auto(photo3.0.clone())
635 .size(inches(2.5), inches(2.1))
636 .at(inches(7.2), inches(1.5))
637 .soft_edges()
638 .build();
639
640 slides.push(
641 SlideContent::new("Image Effects: Soft Edges (Feathered)")
642 .add_image(img1_soft)
643 .add_image(img2_soft)
644 .add_image(img3_soft)
645 .title_color("9B59B6"),
646 );
647
648 // =========================================================================
649 // SLIDE 18: Images with Inner Shadow
650 // =========================================================================
651 println!("🖼️ Slide 18: Images with Inner Shadow");
652
653 let img1_inner = ImageBuilder::auto(photo1.0.clone())
654 .size(inches(2.4), inches(2.4))
655 .at(inches(1.0), inches(1.5))
656 .inner_shadow()
657 .build();
658 let img2_inner = ImageBuilder::auto(photo2.0.clone())
659 .size(inches(2.9), inches(2.1))
660 .at(inches(4.0), inches(1.5))
661 .inner_shadow()
662 .build();
663 let img3_inner = ImageBuilder::auto(photo3.0.clone())
664 .size(inches(2.5), inches(2.1))
665 .at(inches(7.2), inches(1.5))
666 .inner_shadow()
667 .build();
668
669 slides.push(
670 SlideContent::new("Image Effects: Inner Shadow (Depth)")
671 .add_image(img1_inner)
672 .add_image(img2_inner)
673 .add_image(img3_inner)
674 .title_color("E74C3C"),
675 );
676
677 // =========================================================================
678 // SLIDE 19: Images with Blur Effect
679 // =========================================================================
680 println!("🖼️ Slide 19: Images with Blur Effect");
681
682 let img1_blur = ImageBuilder::auto(photo1.0.clone())
683 .size(inches(2.4), inches(2.4))
684 .at(inches(1.0), inches(1.5))
685 .blur()
686 .build();
687 let img2_blur = ImageBuilder::auto(photo2.0.clone())
688 .size(inches(2.9), inches(2.1))
689 .at(inches(4.0), inches(1.5))
690 .blur()
691 .build();
692 let img3_blur = ImageBuilder::auto(photo3.0.clone())
693 .size(inches(2.5), inches(2.1))
694 .at(inches(7.2), inches(1.5))
695 .blur()
696 .build();
697
698 slides.push(
699 SlideContent::new("Image Effects: Blur (Artistic)")
700 .add_image(img1_blur)
701 .add_image(img2_blur)
702 .add_image(img3_blur)
703 .title_color("3498DB"),
704 );
705
706 // =========================================================================
707 // SLIDE 20: Images with Combined Effects
708 // =========================================================================
709 println!("🖼️ Slide 20: Images with Combined Effects");
710
711 let img1_combined = ImageBuilder::auto(photo1.0.clone())
712 .size(inches(2.4), inches(2.4))
713 .at(inches(1.0), inches(1.5))
714 .shadow()
715 .reflection()
716 .build();
717 let img2_combined = ImageBuilder::auto(photo2.0.clone())
718 .size(inches(2.9), inches(2.1))
719 .at(inches(4.0), inches(1.5))
720 .shadow()
721 .reflection()
722 .build();
723 let img3_combined = ImageBuilder::auto(photo3.0.clone())
724 .size(inches(2.5), inches(2.1))
725 .at(inches(7.2), inches(1.5))
726 .shadow()
727 .reflection()
728 .build();
729
730 slides.push(
731 SlideContent::new("Combined Effects: Shadow + Reflection")
732 .add_image(img1_combined)
733 .add_image(img2_combined)
734 .add_image(img3_combined)
735 .title_color("16A085"),
736 );
737
738 // =========================================================================
739 // SLIDE 11: Advanced Table with Borders & Alignment (NEW)
740 // =========================================================================
741 println!("📊 Slide 11: Advanced Table (borders, alignment, merged cells)");
742
743 // Build advanced table using generator's TableBuilder with alignment
744 let advanced_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
745 .add_row(TableRow::new(vec![
746 TableCell::new("Q1 2024 Financial Report")
747 .bold()
748 .background_color("1F4E79")
749 .text_color("FFFFFF")
750 .align_center()
751 .font_size(14),
752 TableCell::new("").background_color("1F4E79"),
753 TableCell::new("").background_color("1F4E79"),
754 TableCell::new("").background_color("1F4E79"),
755 ]))
756 .add_row(TableRow::new(vec![
757 TableCell::new("Category")
758 .bold()
759 .background_color("2E75B6")
760 .text_color("FFFFFF")
761 .align_center(),
762 TableCell::new("Revenue")
763 .bold()
764 .background_color("2E75B6")
765 .text_color("FFFFFF")
766 .align_center(),
767 TableCell::new("Expenses")
768 .bold()
769 .background_color("2E75B6")
770 .text_color("FFFFFF")
771 .align_center(),
772 TableCell::new("Profit")
773 .bold()
774 .background_color("2E75B6")
775 .text_color("FFFFFF")
776 .align_center(),
777 ]))
778 .add_row(TableRow::new(vec![
779 TableCell::new("Product Sales")
780 .text_color("000000")
781 .align_left(),
782 TableCell::new("$1,250,000")
783 .text_color("2E7D32")
784 .align_right(),
785 TableCell::new("$450,000")
786 .text_color("C62828")
787 .align_right(),
788 TableCell::new("$800,000")
789 .bold()
790 .text_color("2E7D32")
791 .align_right(),
792 ]))
793 .add_row(TableRow::new(vec![
794 TableCell::new("Services").text_color("000000").align_left(),
795 TableCell::new("$890,000")
796 .text_color("2E7D32")
797 .align_right(),
798 TableCell::new("$320,000")
799 .text_color("C62828")
800 .align_right(),
801 TableCell::new("$570,000")
802 .bold()
803 .text_color("2E7D32")
804 .align_right(),
805 ]))
806 .add_row(TableRow::new(vec![
807 TableCell::new("Total")
808 .bold()
809 .background_color("E7E6E6")
810 .text_color("000000")
811 .align_left(),
812 TableCell::new("$2,140,000")
813 .bold()
814 .background_color("E7E6E6")
815 .text_color("000000")
816 .align_right(),
817 TableCell::new("$770,000")
818 .bold()
819 .background_color("E7E6E6")
820 .text_color("000000")
821 .align_right(),
822 TableCell::new("$1,370,000")
823 .bold()
824 .background_color("C6EFCE")
825 .text_color("006100")
826 .align_right(),
827 ]))
828 .position(300000, 1600000)
829 .build();
830
831 slides.push(
832 SlideContent::new("Financial Report - Advanced Table")
833 .table(advanced_table)
834 .title_color("1F4E79")
835 .title_bold(true),
836 );
837
838 // =========================================================================
839 // SLIDE 12: Comparison Matrix Table (NEW)
840 // =========================================================================
841 println!("📊 Slide 12: Comparison Matrix Table");
842
843 let comparison_table = TableBuilder::new(vec![2000000, 1500000, 1500000, 1500000])
844 .add_row(TableRow::new(vec![
845 TableCell::new("Feature")
846 .bold()
847 .background_color("4472C4")
848 .text_color("FFFFFF"),
849 TableCell::new("Basic")
850 .bold()
851 .background_color("4472C4")
852 .text_color("FFFFFF"),
853 TableCell::new("Pro")
854 .bold()
855 .background_color("4472C4")
856 .text_color("FFFFFF"),
857 TableCell::new("Enterprise")
858 .bold()
859 .background_color("4472C4")
860 .text_color("FFFFFF"),
861 ]))
862 .add_row(TableRow::new(vec![
863 TableCell::new("Storage").text_color("000000"),
864 TableCell::new("5 GB").text_color("000000"),
865 TableCell::new("50 GB").text_color("000000"),
866 TableCell::new("Unlimited").bold().text_color("2E7D32"),
867 ]))
868 .add_row(TableRow::new(vec![
869 TableCell::new("Users").text_color("000000"),
870 TableCell::new("1").text_color("000000"),
871 TableCell::new("10").text_color("000000"),
872 TableCell::new("Unlimited").bold().text_color("2E7D32"),
873 ]))
874 .add_row(TableRow::new(vec![
875 TableCell::new("Support").text_color("000000"),
876 TableCell::new("Email").text_color("000000"),
877 TableCell::new("24/7 Chat").text_color("000000"),
878 TableCell::new("Dedicated").bold().text_color("2E7D32"),
879 ]))
880 .add_row(TableRow::new(vec![
881 TableCell::new("API Access").text_color("000000"),
882 TableCell::new("No").text_color("C62828"),
883 TableCell::new("Yes").text_color("2E7D32"),
884 TableCell::new("Yes + Priority").bold().text_color("2E7D32"),
885 ]))
886 .add_row(TableRow::new(vec![
887 TableCell::new("Price/month")
888 .bold()
889 .background_color("F2F2F2")
890 .text_color("000000"),
891 TableCell::new("$9")
892 .bold()
893 .background_color("F2F2F2")
894 .text_color("000000"),
895 TableCell::new("$29")
896 .bold()
897 .background_color("F2F2F2")
898 .text_color("000000"),
899 TableCell::new("$99")
900 .bold()
901 .background_color("F2F2F2")
902 .text_color("000000"),
903 ]))
904 .position(500000, 1600000)
905 .build();
906
907 slides.push(
908 SlideContent::new("Pricing Comparison Matrix")
909 .table(comparison_table)
910 .title_color("4472C4")
911 .title_bold(true),
912 );
913
914 // =========================================================================
915 // SLIDE 13: Process Flow with Shapes (NEW - SmartArt-like)
916 // =========================================================================
917 println!("🔷 Slide 13: Process Flow (SmartArt-style)");
918
919 // Create process flow using shapes
920 let step1 = rounded_rect(0.3, 2.2, 1.5, 0.9)
921 .fill(hex("4472C4"))
922 .text("1. Research");
923 let arrow1 = shapes::arrow_right(2.0, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
924 let step2 = rounded_rect(2.5, 2.2, 1.5, 0.9)
925 .fill(hex("ED7D31"))
926 .text("2. Design");
927 let arrow2 = shapes::arrow_right(4.2, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
928 let step3 = rounded_rect(4.7, 2.2, 1.5, 0.9)
929 .fill(hex("70AD47"))
930 .text("3. Develop");
931 let arrow3 = shapes::arrow_right(6.3, 2.4, 0.4, 0.4).fill(hex("A5A5A5"));
932 let step4 = rounded_rect(6.9, 2.2, 1.5, 0.9)
933 .fill(hex("5B9BD5"))
934 .text("4. Deploy");
935
936 slides.push(
937 SlideContent::new("Development Process Flow")
938 .add_shape(step1)
939 .add_shape(arrow1)
940 .add_shape(step2)
941 .add_shape(arrow2)
942 .add_shape(step3)
943 .add_shape(arrow3)
944 .add_shape(step4)
945 .title_color("1F497D")
946 .title_bold(true),
947 );
948
949 // =========================================================================
950 // SLIDE 14: Organization Chart with Shapes (NEW)
951 // =========================================================================
952 println!("🔷 Slide 14: Organization Chart");
953
954 // CEO at top
955 let ceo = rounded_rect(3.8, 1.5, 2.2, 0.7)
956 .fill(hex("1F4E79"))
957 .text("CEO");
958
959 // Vertical line from CEO
960 let line1 = rect(4.9, 2.2, 0.1, 0.4).fill(hex("A5A5A5"));
961
962 // Horizontal connector
963 let hline = rect(2.1, 2.6, 5.6, 0.05).fill(hex("A5A5A5"));
964
965 // CTO, CFO, COO
966 let cto = rounded_rect(1.1, 2.8, 2.0, 0.5)
967 .fill(hex("2E75B6"))
968 .text("CTO");
969 let cfo = rounded_rect(3.9, 2.8, 2.0, 0.5)
970 .fill(hex("2E75B6"))
971 .text("CFO");
972 let coo = rounded_rect(6.8, 2.8, 2.0, 0.5)
973 .fill(hex("2E75B6"))
974 .text("COO");
975
976 // Vertical lines to departments
977 let vline1 = rect(2.0, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
978 let vline2 = rect(4.9, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
979 let vline3 = rect(7.7, 2.7, 0.05, 0.16).fill(hex("A5A5A5"));
980
981 // Teams under CTO
982 let eng = rect(0.5, 3.6, 1.3, 0.4)
983 .fill(hex("BDD7EE"))
984 .text("Engineering");
985 let product = rect(2.0, 3.6, 1.3, 0.4).fill(hex("BDD7EE")).text("Product");
986
987 slides.push(
988 SlideContent::new("Organization Structure")
989 .add_shape(ceo)
990 .add_shape(line1)
991 .add_shape(hline)
992 .add_shape(cto)
993 .add_shape(cfo)
994 .add_shape(coo)
995 .add_shape(vline1)
996 .add_shape(vline2)
997 .add_shape(vline3)
998 .add_shape(eng)
999 .add_shape(product)
1000 .title_color("1F4E79")
1001 .title_bold(true),
1002 );
1003
1004 // =========================================================================
1005 // SLIDE 15: PDCA Cycle Diagram (NEW)
1006 // =========================================================================
1007 println!("🔷 Slide 15: PDCA Cycle Diagram");
1008
1009 // Four quadrants for PDCA
1010 let plan = rounded_rect(1.6, 1.75, 2.7, 1.6)
1011 .fill(hex("4472C4"))
1012 .text("PLAN\n\nDefine goals\nand strategy");
1013 let do_box = rounded_rect(4.9, 1.75, 2.7, 1.6)
1014 .fill(hex("ED7D31"))
1015 .text("DO\n\nImplement\nthe plan");
1016 let check = rounded_rect(4.9, 3.6, 2.7, 1.6)
1017 .fill(hex("70AD47"))
1018 .text("CHECK\n\nMeasure\nresults");
1019 let act = rounded_rect(1.6, 3.6, 2.7, 1.6)
1020 .fill(hex("FFC000"))
1021 .text("ACT\n\nAdjust and\nimprove");
1022
1023 // Arrows between quadrants
1024 let arr1 = shapes::arrow_right(4.5, 2.3, 0.3, 0.3).fill(hex("A5A5A5"));
1025 let arr2 = shapes::arrow_down(6.1, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1026 let arr3 = shapes::arrow_left(4.5, 4.2, 0.3, 0.3).fill(hex("A5A5A5"));
1027 let arr4 = shapes::arrow_up(2.8, 3.5, 0.3, 0.2).fill(hex("A5A5A5"));
1028
1029 slides.push(
1030 SlideContent::new("PDCA Continuous Improvement Cycle")
1031 .add_shape(plan)
1032 .add_shape(do_box)
1033 .add_shape(check)
1034 .add_shape(act)
1035 .add_shape(arr1)
1036 .add_shape(arr2)
1037 .add_shape(arr3)
1038 .add_shape(arr4)
1039 .title_color("1F497D")
1040 .title_bold(true),
1041 );
1042
1043 // =========================================================================
1044 // SLIDE 16: Pyramid Diagram (Maslow's Hierarchy) (NEW)
1045 // =========================================================================
1046 println!("🔷 Slide 16: Pyramid Diagram");
1047
1048 // Build pyramid from bottom to top
1049 let level5 = shapes::dim(
1050 ShapeType::Trapezoid,
1051 Dimension::Inches(0.5),
1052 Dimension::Inches(4.4),
1053 Dimension::Inches(8.7),
1054 Dimension::Inches(0.7),
1055 )
1056 .fill(hex("C00000"))
1057 .text("Physiological Needs - Food, Water, Shelter");
1058 let level4 = shapes::dim(
1059 ShapeType::Trapezoid,
1060 Dimension::Inches(1.1),
1061 Dimension::Inches(3.7),
1062 Dimension::Inches(7.7),
1063 Dimension::Inches(0.7),
1064 )
1065 .fill(hex("ED7D31"))
1066 .text("Safety Needs - Security, Stability");
1067 let level3 = shapes::dim(
1068 ShapeType::Trapezoid,
1069 Dimension::Inches(1.6),
1070 Dimension::Inches(3.1),
1071 Dimension::Inches(6.6),
1072 Dimension::Inches(0.7),
1073 )
1074 .fill(hex("FFC000"))
1075 .text("Love & Belonging - Relationships");
1076 let level2 = shapes::dim(
1077 ShapeType::Trapezoid,
1078 Dimension::Inches(2.2),
1079 Dimension::Inches(2.4),
1080 Dimension::Inches(5.5),
1081 Dimension::Inches(0.7),
1082 )
1083 .fill(hex("70AD47"))
1084 .text("Esteem - Achievement, Respect");
1085 let level1 = triangle(2.7, 1.6, 4.4, 0.8)
1086 .fill(hex("4472C4"))
1087 .text("Self-Actualization");
1088
1089 slides.push(
1090 SlideContent::new("Maslow's Hierarchy of Needs")
1091 .add_shape(level5)
1092 .add_shape(level4)
1093 .add_shape(level3)
1094 .add_shape(level2)
1095 .add_shape(level1)
1096 .title_color("1F497D")
1097 .title_bold(true),
1098 );
1099
1100 // =========================================================================
1101 // SLIDE 17: Venn Diagram (NEW)
1102 // =========================================================================
1103 println!("🔷 Slide 17: Venn Diagram");
1104
1105 // Three overlapping circles
1106 let circle1 = circle(1.6, 2.0, 3.3).fill(hex("4472C4")).text("Skills");
1107 let circle2 = circle(3.8, 2.0, 3.3).fill(hex("ED7D31")).text("Passion");
1108 let circle3 = circle(2.7, 3.5, 3.3)
1109 .fill(hex("70AD47"))
1110 .text("Market Need");
1111
1112 // Center label
1113 let center = ellipse(3.5, 3.1, 1.75, 0.9)
1114 .fill(hex("FFFFFF"))
1115 .text("IKIGAI");
1116
1117 slides.push(
1118 SlideContent::new("Finding Your Ikigai - Venn Diagram")
1119 .add_shape(circle1)
1120 .add_shape(circle2)
1121 .add_shape(circle3)
1122 .add_shape(center)
1123 .title_color("1F497D")
1124 .title_bold(true),
1125 );
1126
1127 // =========================================================================
1128 // SLIDE 18: Timeline/Roadmap (NEW)
1129 // =========================================================================
1130 println!("📊 Slide 18: Project Timeline");
1131
1132 let timeline_table = TableBuilder::new(vec![1500000, 1500000, 1500000, 1500000, 1500000])
1133 .add_row(TableRow::new(vec![
1134 TableCell::new("Q1 2024")
1135 .bold()
1136 .background_color("4472C4")
1137 .text_color("FFFFFF"),
1138 TableCell::new("Q2 2024")
1139 .bold()
1140 .background_color("4472C4")
1141 .text_color("FFFFFF"),
1142 TableCell::new("Q3 2024")
1143 .bold()
1144 .background_color("4472C4")
1145 .text_color("FFFFFF"),
1146 TableCell::new("Q4 2024")
1147 .bold()
1148 .background_color("4472C4")
1149 .text_color("FFFFFF"),
1150 TableCell::new("Q1 2025")
1151 .bold()
1152 .background_color("4472C4")
1153 .text_color("FFFFFF"),
1154 ]))
1155 .add_row(TableRow::new(vec![
1156 TableCell::new("Research\n& Planning")
1157 .background_color("BDD7EE")
1158 .text_color("1F497D"),
1159 TableCell::new("Design\nPhase")
1160 .background_color("BDD7EE")
1161 .text_color("1F497D"),
1162 TableCell::new("Development\nSprint 1-3")
1163 .background_color("C6EFCE")
1164 .text_color("006100"),
1165 TableCell::new("Testing\n& QA")
1166 .background_color("FCE4D6")
1167 .text_color("C65911"),
1168 TableCell::new("Launch\n& Support")
1169 .background_color("E2EFDA")
1170 .text_color("375623"),
1171 ]))
1172 .add_row(TableRow::new(vec![
1173 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1174 TableCell::new("✓ Complete").bold().text_color("2E7D32"),
1175 TableCell::new("In Progress").text_color("ED7D31"),
1176 TableCell::new("Planned").text_color("7F7F7F"),
1177 TableCell::new("Planned").text_color("7F7F7F"),
1178 ]))
1179 .position(300000, 2000000)
1180 .build();
1181
1182 slides.push(
1183 SlideContent::new("Project Roadmap 2024-2025")
1184 .table(timeline_table)
1185 .title_color("1F497D")
1186 .title_bold(true),
1187 );
1188
1189 // =========================================================================
1190 // SLIDE 19: Dashboard Summary (NEW - using Dimension API)
1191 // =========================================================================
1192 println!("🔷 Slide 19: Dashboard with KPIs (Dimension API)");
1193
1194 // KPI boxes using ratio-based positioning — automatically adapts to any slide size
1195 let kpi1 = shapes::dim(
1196 ShapeType::RoundedRectangle,
1197 Dimension::percent(3.0),
1198 Dimension::percent(23.0),
1199 Dimension::percent(22.0),
1200 Dimension::percent(18.0),
1201 )
1202 .fill(hex("4472C4"))
1203 .text("Revenue\n\n$2.14M\n+15% YoY");
1204
1205 let kpi2 = shapes::dim(
1206 ShapeType::RoundedRectangle,
1207 Dimension::percent(27.0),
1208 Dimension::percent(23.0),
1209 Dimension::percent(22.0),
1210 Dimension::percent(18.0),
1211 )
1212 .fill(hex("70AD47"))
1213 .text("Customers\n\n12,450\n+22% YoY");
1214
1215 let kpi3 = shapes::dim(
1216 ShapeType::RoundedRectangle,
1217 Dimension::percent(51.0),
1218 Dimension::percent(23.0),
1219 Dimension::percent(22.0),
1220 Dimension::percent(18.0),
1221 )
1222 .fill(hex("ED7D31"))
1223 .text("NPS Score\n\n72\n+8 pts");
1224
1225 let kpi4 = shapes::dim(
1226 ShapeType::RoundedRectangle,
1227 Dimension::percent(75.0),
1228 Dimension::percent(23.0),
1229 Dimension::percent(22.0),
1230 Dimension::percent(18.0),
1231 )
1232 .fill(hex("5B9BD5"))
1233 .text("Retention\n\n94%\n+3% YoY");
1234
1235 // Status indicators using mixed units: percent for X, inches for size
1236 let status1 = shapes::dim(
1237 ShapeType::Ellipse,
1238 Dimension::percent(14.0),
1239 Dimension::percent(42.0),
1240 Dimension::Inches(0.3),
1241 Dimension::Inches(0.3),
1242 )
1243 .fill(hex("70AD47"));
1244 let status2 = shapes::dim(
1245 ShapeType::Ellipse,
1246 Dimension::percent(38.0),
1247 Dimension::percent(42.0),
1248 Dimension::Inches(0.3),
1249 Dimension::Inches(0.3),
1250 )
1251 .fill(hex("70AD47"));
1252 let status3 = shapes::dim(
1253 ShapeType::Ellipse,
1254 Dimension::percent(62.0),
1255 Dimension::percent(42.0),
1256 Dimension::Inches(0.3),
1257 Dimension::Inches(0.3),
1258 )
1259 .fill(hex("FFC000"));
1260 let status4 = shapes::dim(
1261 ShapeType::Ellipse,
1262 Dimension::percent(86.0),
1263 Dimension::percent(42.0),
1264 Dimension::Inches(0.3),
1265 Dimension::Inches(0.3),
1266 )
1267 .fill(hex("70AD47"));
1268
1269 slides.push(
1270 SlideContent::new("Executive Dashboard - Q1 2024")
1271 .add_shape(kpi1)
1272 .add_shape(kpi2)
1273 .add_shape(kpi3)
1274 .add_shape(kpi4)
1275 .add_shape(status1)
1276 .add_shape(status2)
1277 .add_shape(status3)
1278 .add_shape(status4)
1279 .title_color("1F497D")
1280 .title_bold(true),
1281 );
1282
1283 // =========================================================================
1284 // SLIDE 20: Summary Slide (NEW)
1285 // =========================================================================
1286 println!("📝 Slide 20: Summary with Speaker Notes");
1287
1288 slides.push(
1289 SlideContent::new("Summary & Next Steps")
1290 .layout(SlideLayout::TitleAndContent)
1291 .title_color("1F497D")
1292 .title_bold(true)
1293 .add_bullet("Completed: Research, Design, Initial Development")
1294 .add_bullet("In Progress: Sprint 3 Development")
1295 .add_bullet("Next: QA Testing Phase (Q4 2024)")
1296 .add_bullet("Launch Target: Q1 2025")
1297 .add_bullet("Key Risks: Resource constraints, Timeline pressure")
1298 .content_size(24)
1299 .notes("Speaker Notes:\n\n1. Emphasize the progress made\n2. Highlight key achievements\n3. Address any concerns about timeline\n4. Open for Q&A")
1300 );
1301
1302 // =========================================================================
1303 // SLIDE 21: Bullet Styles (NEW v0.2.1)
1304 // =========================================================================
1305 println!("🔢 Slide 21: Bullet Styles (NEW)");
1306
1307 // Numbered list
1308 slides.push(
1309 SlideContent::new("Bullet Styles - Numbered List")
1310 .layout(SlideLayout::TitleAndContent)
1311 .title_color("1F497D")
1312 .title_bold(true)
1313 .with_bullet_style(BulletStyle::Number)
1314 .add_bullet("First numbered item")
1315 .add_bullet("Second numbered item")
1316 .add_bullet("Third numbered item")
1317 .add_bullet("Fourth numbered item")
1318 .content_size(28),
1319 );
1320
1321 // =========================================================================
1322 // SLIDE 22: Lettered Lists (NEW v0.2.1)
1323 // =========================================================================
1324 println!("🔤 Slide 22: Lettered Lists (NEW)");
1325
1326 slides.push(
1327 SlideContent::new("Bullet Styles - Lettered Lists")
1328 .layout(SlideLayout::TitleAndContent)
1329 .title_color("1F497D")
1330 .title_bold(true)
1331 .add_lettered("Option A - First choice")
1332 .add_lettered("Option B - Second choice")
1333 .add_lettered("Option C - Third choice")
1334 .add_lettered("Option D - Fourth choice")
1335 .content_size(28),
1336 );
1337
1338 // =========================================================================
1339 // SLIDE 23: Roman Numerals (NEW v0.2.1)
1340 // =========================================================================
1341 println!("🏛️ Slide 23: Roman Numerals (NEW)");
1342
1343 slides.push(
1344 SlideContent::new("Bullet Styles - Roman Numerals")
1345 .layout(SlideLayout::TitleAndContent)
1346 .title_color("1F497D")
1347 .title_bold(true)
1348 .with_bullet_style(BulletStyle::RomanUpper)
1349 .add_bullet("Chapter I - Introduction")
1350 .add_bullet("Chapter II - Background")
1351 .add_bullet("Chapter III - Methodology")
1352 .add_bullet("Chapter IV - Results")
1353 .add_bullet("Chapter V - Conclusion")
1354 .content_size(28),
1355 );
1356
1357 // =========================================================================
1358 // SLIDE 24: Custom Bullets (NEW v0.2.1)
1359 // =========================================================================
1360 println!("⭐ Slide 24: Custom Bullets (NEW)");
1361
1362 slides.push(
1363 SlideContent::new("Bullet Styles - Custom Characters")
1364 .layout(SlideLayout::TitleAndContent)
1365 .title_color("1F497D")
1366 .title_bold(true)
1367 .add_styled_bullet("Star bullet point", BulletStyle::Custom('★'))
1368 .add_styled_bullet("Arrow bullet point", BulletStyle::Custom('→'))
1369 .add_styled_bullet("Check bullet point", BulletStyle::Custom('✓'))
1370 .add_styled_bullet("Diamond bullet point", BulletStyle::Custom('◆'))
1371 .add_styled_bullet("Heart bullet point", BulletStyle::Custom('♥'))
1372 .content_size(28),
1373 );
1374
1375 // =========================================================================
1376 // SLIDE 25: Sub-bullets / Hierarchy (NEW v0.2.1)
1377 // =========================================================================
1378 println!("📊 Slide 25: Sub-bullets Hierarchy (NEW)");
1379
1380 slides.push(
1381 SlideContent::new("Bullet Styles - Hierarchical Lists")
1382 .layout(SlideLayout::TitleAndContent)
1383 .title_color("1F497D")
1384 .title_bold(true)
1385 .add_bullet("Main Topic 1")
1386 .add_sub_bullet("Supporting detail A")
1387 .add_sub_bullet("Supporting detail B")
1388 .add_bullet("Main Topic 2")
1389 .add_sub_bullet("Supporting detail C")
1390 .add_sub_bullet("Supporting detail D")
1391 .add_bullet("Main Topic 3")
1392 .content_size(24),
1393 );
1394
1395 // =========================================================================
1396 // SLIDE 26: Text Enhancements (NEW v0.2.1)
1397 // =========================================================================
1398 println!("✏️ Slide 26: Text Enhancements (NEW)");
1399
1400 // Use BulletPoint with formatting
1401 let strikethrough_bullet =
1402 BulletPoint::new("Strikethrough: This text is crossed out").strikethrough();
1403 let highlight_bullet =
1404 BulletPoint::new("Highlight: Yellow background for emphasis").highlight("FFFF00");
1405 let subscript_bullet = BulletPoint::new("Subscript: H₂O - for chemical formulas").subscript();
1406 let superscript_bullet =
1407 BulletPoint::new("Superscript: x² - for math expressions").superscript();
1408 let bold_colored = BulletPoint::new("Combined: Bold + Red color")
1409 .bold()
1410 .color("FF0000");
1411
1412 let mut text_enhancements_slide = SlideContent::new("Text Enhancements - New Formatting")
1413 .layout(SlideLayout::TitleAndContent)
1414 .title_color("1F497D")
1415 .title_bold(true)
1416 .content_size(24);
1417 text_enhancements_slide.bullets.push(strikethrough_bullet);
1418 text_enhancements_slide.bullets.push(highlight_bullet);
1419 text_enhancements_slide.bullets.push(subscript_bullet);
1420 text_enhancements_slide.bullets.push(superscript_bullet);
1421 text_enhancements_slide.bullets.push(bold_colored);
1422
1423 slides.push(text_enhancements_slide);
1424
1425 // =========================================================================
1426 // SLIDE 27: Font Size Presets (NEW v0.2.1)
1427 // =========================================================================
1428 println!("🔤 Slide 27: Font Size Presets (NEW)");
1429
1430 // Demonstrate different font sizes per bullet
1431 let large_bullet = BulletPoint::new(&format!(
1432 "LARGE: {}pt - Extra large text",
1433 font_sizes::LARGE
1434 ))
1435 .font_size(font_sizes::LARGE);
1436 let heading_bullet = BulletPoint::new(&format!(
1437 "HEADING: {}pt - Section headers",
1438 font_sizes::HEADING
1439 ))
1440 .font_size(font_sizes::HEADING);
1441 let body_bullet = BulletPoint::new(&format!("BODY: {}pt - Regular content", font_sizes::BODY))
1442 .font_size(font_sizes::BODY);
1443 let small_bullet = BulletPoint::new(&format!("SMALL: {}pt - Smaller text", font_sizes::SMALL))
1444 .font_size(font_sizes::SMALL);
1445 let caption_bullet = BulletPoint::new(&format!(
1446 "CAPTION: {}pt - Captions and notes",
1447 font_sizes::CAPTION
1448 ))
1449 .font_size(font_sizes::CAPTION);
1450
1451 let mut font_size_slide = SlideContent::new("Font Size Presets - Each line different size")
1452 .layout(SlideLayout::TitleAndContent)
1453 .title_color("1F497D")
1454 .title_bold(true)
1455 .title_size(font_sizes::TITLE);
1456 font_size_slide.bullets.push(large_bullet);
1457 font_size_slide.bullets.push(heading_bullet);
1458 font_size_slide.bullets.push(body_bullet);
1459 font_size_slide.bullets.push(small_bullet);
1460 font_size_slide.bullets.push(caption_bullet);
1461
1462 slides.push(font_size_slide);
1463
1464 // =========================================================================
1465 // SLIDE 28: Theme Colors (NEW v0.2.1)
1466 // =========================================================================
1467 println!("🎨 Slide 28: Theme Colors (NEW)");
1468
1469 // Create shapes with theme colors
1470 let corporate_shape = rect(0.5, 1.75, 2.0, 0.9)
1471 .fill(hex(themes::CORPORATE.primary))
1472 .text("Corporate");
1473
1474 let modern_shape = rect(2.7, 1.75, 2.0, 0.9)
1475 .fill(hex(themes::MODERN.primary))
1476 .text("Modern");
1477
1478 let vibrant_shape = rect(4.9, 1.75, 2.0, 0.9)
1479 .fill(hex(themes::VIBRANT.primary))
1480 .text("Vibrant");
1481
1482 let dark_shape = rect(7.1, 1.75, 2.0, 0.9)
1483 .fill(hex(themes::DARK.primary))
1484 .text("Dark");
1485
1486 let nature_shape = rect(0.5, 3.0, 2.0, 0.9)
1487 .fill(hex(themes::NATURE.primary))
1488 .text("Nature");
1489
1490 let tech_shape = rect(2.7, 3.0, 2.0, 0.9)
1491 .fill(hex(themes::TECH.primary))
1492 .text("Tech");
1493
1494 let carbon_shape = rect(4.9, 3.0, 2.0, 0.9)
1495 .fill(hex(themes::CARBON.primary))
1496 .text("Carbon");
1497
1498 slides.push(
1499 SlideContent::new("Theme Color Palettes")
1500 .layout(SlideLayout::TitleAndContent)
1501 .title_color("1F497D")
1502 .title_bold(true)
1503 .add_shape(corporate_shape)
1504 .add_shape(modern_shape)
1505 .add_shape(vibrant_shape)
1506 .add_shape(dark_shape)
1507 .add_shape(nature_shape)
1508 .add_shape(tech_shape)
1509 .add_shape(carbon_shape),
1510 );
1511
1512 // =========================================================================
1513 // SLIDE 29: Material & Carbon Design Colors (NEW v0.2.1)
1514 // =========================================================================
1515 println!("🌈 Slide 29: Material & Carbon Colors (NEW)");
1516
1517 // Material Design colors
1518 let material_red = rect(0.5, 1.75, 1.3, 0.7)
1519 .fill(hex(colors::MATERIAL_RED))
1520 .text("M-Red");
1521
1522 let material_blue = rect(2.1, 1.75, 1.3, 0.7)
1523 .fill(hex(colors::MATERIAL_BLUE))
1524 .text("M-Blue");
1525
1526 let material_green = rect(3.6, 1.75, 1.3, 0.7)
1527 .fill(hex(colors::MATERIAL_GREEN))
1528 .text("M-Green");
1529
1530 let material_orange = rect(5.1, 1.75, 1.3, 0.7)
1531 .fill(hex(colors::MATERIAL_ORANGE))
1532 .text("M-Orange");
1533
1534 let material_purple = rect(6.7, 1.75, 1.3, 0.7)
1535 .fill(hex(colors::MATERIAL_PURPLE))
1536 .text("M-Purple");
1537
1538 // Carbon Design colors
1539 let carbon_blue = rect(0.5, 2.7, 1.3, 0.7)
1540 .fill(hex(colors::CARBON_BLUE_60))
1541 .text("C-Blue");
1542
1543 let carbon_green = rect(2.1, 2.7, 1.3, 0.7)
1544 .fill(hex(colors::CARBON_GREEN_50))
1545 .text("C-Green");
1546
1547 let carbon_red = rect(3.6, 2.7, 1.3, 0.7)
1548 .fill(hex(colors::CARBON_RED_60))
1549 .text("C-Red");
1550
1551 let carbon_purple = rect(5.1, 2.7, 1.3, 0.7)
1552 .fill(hex(colors::CARBON_PURPLE_60))
1553 .text("C-Purple");
1554
1555 let carbon_gray = rect(6.7, 2.7, 1.3, 0.7)
1556 .fill(hex(colors::CARBON_GRAY_100))
1557 .text("C-Gray");
1558
1559 slides.push(
1560 SlideContent::new("Material & Carbon Design Colors")
1561 .layout(SlideLayout::TitleAndContent)
1562 .title_color("1F497D")
1563 .title_bold(true)
1564 .add_shape(material_red)
1565 .add_shape(material_blue)
1566 .add_shape(material_green)
1567 .add_shape(material_orange)
1568 .add_shape(material_purple)
1569 .add_shape(carbon_blue)
1570 .add_shape(carbon_green)
1571 .add_shape(carbon_red)
1572 .add_shape(carbon_purple)
1573 .add_shape(carbon_gray),
1574 );
1575
1576 // =========================================================================
1577 // SLIDE 30: Image from Base64 (NEW v0.2.1)
1578 // =========================================================================
1579 println!("🖼️ Slide 30: Image from Base64 (NEW)");
1580
1581 // 1x1 red PNG pixel in base64
1582 let _red_pixel_base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
1583
1584 // Create image from base64 (demonstrating the API)
1585 let _base64_image = ImageBuilder::from_base64(_red_pixel_base64, 914400, 914400, "PNG")
1586 .position(4000000, 2500000)
1587 .build();
1588
1589 slides.push(
1590 SlideContent::new("Image Loading - New Methods")
1591 .layout(SlideLayout::TitleAndContent)
1592 .title_color("1F497D")
1593 .title_bold(true)
1594 .add_bullet("Image::new(path) - Load from file path")
1595 .add_bullet("Image::from_base64(data) - Load from base64 string")
1596 .add_bullet("Image::from_bytes(data) - Load from raw bytes")
1597 .add_bullet("ImageBuilder for fluent API configuration")
1598 .add_bullet("Built-in base64 decoder (no external deps)")
1599 .content_size(24),
1600 );
1601
1602 // =========================================================================
1603 // SLIDE 31: Feature Summary (NEW v0.2.1)
1604 // =========================================================================
1605 println!("📋 Slide 31: v0.2.1 Feature Summary (NEW)");
1606
1607 slides.push(
1608 SlideContent::new("New Features in v0.2.1")
1609 .layout(SlideLayout::TitleAndContent)
1610 .title_color("1F497D")
1611 .title_bold(true)
1612 .add_numbered("BulletStyle: Number, Letter, Roman, Custom")
1613 .add_numbered("TextFormat: Strikethrough, Highlight")
1614 .add_numbered("TextFormat: Subscript, Superscript")
1615 .add_numbered("Font size presets in prelude")
1616 .add_numbered("Image::from_base64 and from_bytes")
1617 .add_numbered("Theme color palettes (7 themes)")
1618 .add_numbered("Material & Carbon Design colors")
1619 .content_size(24),
1620 );
1621
1622 // =========================================================================
1623 // SLIDE 32: Slide Show Settings - Comparison Table (REAL: embedded in presProps.xml)
1624 // =========================================================================
1625 println!("🎬 Slide 34: Slide Show Settings (Visual)");
1626
1627 let show_speaker = SlideShowSettings::new().pen_color(PenColor::red());
1628 let show_kiosk = SlideShowSettings::kiosk();
1629 let _show_range = SlideShowSettings::new()
1630 .show_type(ShowType::Browsed)
1631 .slide_range(SlideRange::Range { start: 1, end: 10 })
1632 .without_animation(true);
1633 let _speaker_xml = show_speaker.to_xml();
1634 let _kiosk_xml = show_kiosk.to_xml();
1635
1636 let show_table = TableBuilder::new(vec![2000000, 2000000, 2000000, 2000000])
1637 .add_row(TableRow::new(vec![
1638 TableCell::new("Setting")
1639 .bold()
1640 .background_color("1F4E79")
1641 .text_color("FFFFFF"),
1642 TableCell::new("Speaker")
1643 .bold()
1644 .background_color("4472C4")
1645 .text_color("FFFFFF"),
1646 TableCell::new("Kiosk")
1647 .bold()
1648 .background_color("ED7D31")
1649 .text_color("FFFFFF"),
1650 TableCell::new("Browsed")
1651 .bold()
1652 .background_color("70AD47")
1653 .text_color("FFFFFF"),
1654 ]))
1655 .add_row(TableRow::new(vec![
1656 TableCell::new("Loop").bold().background_color("D6E4F0"),
1657 TableCell::new("No"),
1658 TableCell::new("Yes").bold().text_color("2E7D32"),
1659 TableCell::new("No"),
1660 ]))
1661 .add_row(TableRow::new(vec![
1662 TableCell::new("Narration")
1663 .bold()
1664 .background_color("D6E4F0"),
1665 TableCell::new("Yes"),
1666 TableCell::new("No").text_color("C62828"),
1667 TableCell::new("Yes"),
1668 ]))
1669 .add_row(TableRow::new(vec![
1670 TableCell::new("Animation")
1671 .bold()
1672 .background_color("D6E4F0"),
1673 TableCell::new("Yes"),
1674 TableCell::new("Yes"),
1675 TableCell::new("No").text_color("C62828"),
1676 ]))
1677 .add_row(TableRow::new(vec![
1678 TableCell::new("Timings").bold().background_color("D6E4F0"),
1679 TableCell::new("Yes"),
1680 TableCell::new("Auto"),
1681 TableCell::new("Yes"),
1682 ]))
1683 .add_row(TableRow::new(vec![
1684 TableCell::new("Slide Range")
1685 .bold()
1686 .background_color("D6E4F0"),
1687 TableCell::new("All"),
1688 TableCell::new("All"),
1689 TableCell::new("1-10"),
1690 ]))
1691 .add_row(TableRow::new(vec![
1692 TableCell::new("Pen Color")
1693 .bold()
1694 .background_color("D6E4F0"),
1695 TableCell::new("Red").text_color("FF0000"),
1696 TableCell::new("Red").text_color("FF0000"),
1697 TableCell::new("Red").text_color("FF0000"),
1698 ]))
1699 .position(300000, 1600000)
1700 .build();
1701
1702 // Mode icons
1703 let icon_speaker = rounded_rect(0.3, 4.6, 2.7, 0.7)
1704 .fill(hex("4472C4"))
1705 .text("Speaker: Full control");
1706 let icon_kiosk = rounded_rect(3.4, 4.6, 2.7, 0.7)
1707 .fill(hex("ED7D31"))
1708 .text("Kiosk: Auto-loop");
1709 let icon_browsed = rounded_rect(6.5, 4.6, 2.7, 0.7)
1710 .fill(hex("70AD47"))
1711 .text("Browsed: Scrollbar");
1712
1713 slides.push(
1714 SlideContent::new("Slide Show Settings - Mode Comparison")
1715 .table(show_table)
1716 .add_shape(icon_speaker)
1717 .add_shape(icon_kiosk)
1718 .add_shape(icon_browsed)
1719 .title_color("1F497D")
1720 .title_bold(true),
1721 );
1722
1723 // =========================================================================
1724 // SLIDE 35: Print Settings - Visual Handout Grid
1725 // =========================================================================
1726 println!("🖨️ Slide 35: Print Settings & Handouts (Visual)");
1727
1728 let print = PrintSettings::new()
1729 .print_what(PrintWhat::Handouts)
1730 .color_mode(PrintColorMode::Grayscale)
1731 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1732 .frame_slides(true)
1733 .header("Q1 2025 Strategy Review")
1734 .footer("Confidential - Internal Use Only")
1735 .print_date(true)
1736 .print_page_numbers(true);
1737 let _prnpr_xml = print.to_prnpr_xml();
1738 let _handout_xml = print.to_handout_master_xml();
1739
1740 // Visual: 6-slide handout grid (2 cols x 3 rows)
1741 let hdr = rect(0.3, 1.6, 4.6, 0.3)
1742 .fill(hex("E7E6E6"))
1743 .text("Q1 2025 Strategy Review");
1744 // Row 1
1745 let s1 = rect(0.4, 2.2, 2.0, 1.2)
1746 .stroke(hex("999999"), 1.0)
1747 .text("Slide 1");
1748 let s2 = rect(2.7, 2.2, 2.0, 1.2)
1749 .stroke(hex("999999"), 1.0)
1750 .text("Slide 2");
1751 // Row 2
1752 let s3 = rect(0.4, 3.5, 2.0, 1.2)
1753 .stroke(hex("999999"), 1.0)
1754 .text("Slide 3");
1755 let s4 = rect(2.7, 3.5, 2.0, 1.2)
1756 .stroke(hex("999999"), 1.0)
1757 .text("Slide 4");
1758 // Row 3
1759 let s5 = rect(0.4, 4.8, 2.0, 1.2)
1760 .stroke(hex("999999"), 1.0)
1761 .text("Slide 5");
1762 let s6 = rect(2.7, 4.8, 2.0, 1.2)
1763 .stroke(hex("999999"), 1.0)
1764 .text("Slide 6");
1765 let ftr = rect(0.3, 6.1, 4.6, 0.3)
1766 .fill(hex("E7E6E6"))
1767 .text("Confidential - Internal Use Only");
1768
1769 // Settings summary table on the right
1770 let print_table = TableBuilder::new(vec![1800000, 2000000])
1771 .add_row(TableRow::new(vec![
1772 TableCell::new("Print Settings")
1773 .bold()
1774 .background_color("1F4E79")
1775 .text_color("FFFFFF"),
1776 TableCell::new("").background_color("1F4E79"),
1777 ]))
1778 .add_row(TableRow::new(vec![
1779 TableCell::new("Print What")
1780 .bold()
1781 .background_color("D6E4F0"),
1782 TableCell::new("Handouts"),
1783 ]))
1784 .add_row(TableRow::new(vec![
1785 TableCell::new("Color Mode")
1786 .bold()
1787 .background_color("D6E4F0"),
1788 TableCell::new("Grayscale"),
1789 ]))
1790 .add_row(TableRow::new(vec![
1791 TableCell::new("Layout").bold().background_color("D6E4F0"),
1792 TableCell::new("6 slides/page"),
1793 ]))
1794 .add_row(TableRow::new(vec![
1795 TableCell::new("Frame Slides")
1796 .bold()
1797 .background_color("D6E4F0"),
1798 TableCell::new("Yes"),
1799 ]))
1800 .add_row(TableRow::new(vec![
1801 TableCell::new("Date").bold().background_color("D6E4F0"),
1802 TableCell::new("Yes"),
1803 ]))
1804 .add_row(TableRow::new(vec![
1805 TableCell::new("Page Numbers")
1806 .bold()
1807 .background_color("D6E4F0"),
1808 TableCell::new("Yes"),
1809 ]))
1810 .position(5000000, 1800000)
1811 .build();
1812
1813 slides.push(
1814 SlideContent::new("Print Handout - 6 Slides Per Page")
1815 .table(print_table)
1816 .add_shape(hdr)
1817 .add_shape(s1)
1818 .add_shape(s2)
1819 .add_shape(s3)
1820 .add_shape(s4)
1821 .add_shape(s5)
1822 .add_shape(s6)
1823 .add_shape(ftr)
1824 .title_color("1F497D")
1825 .title_bold(true),
1826 );
1827
1828 // =========================================================================
1829 // SLIDE 36: Advanced Table Merging - Actual Merged Table
1830 // =========================================================================
1831 println!("📊 Slide 36: Advanced Table Merging (Visual)");
1832
1833 // Use TableMergeMap to compute states, then build a visual table
1834 let mut merge_map = TableMergeMap::new(5, 4);
1835 merge_map.merge_cells(0, 0, 1, 4).unwrap(); // Title row spans all 4 cols
1836 merge_map.merge_cells(1, 0, 2, 1).unwrap(); // "Products" spans 2 rows
1837 merge_map.merge_cells(3, 0, 2, 1).unwrap(); // "Services" spans 2 rows
1838
1839 // Show merge state labels
1840 let state_00 = merge_map.cell_state(0, 0); // Anchor gridSpan=4
1841 let state_01 = merge_map.cell_state(0, 1); // HMerge
1842 let state_10 = merge_map.cell_state(1, 0); // Anchor rowSpan=2
1843 let state_20 = merge_map.cell_state(2, 0); // VMerge
1844 println!(" ├── (0,0): {}", state_00.to_xml_attrs().trim());
1845 println!(" ├── (0,1): {}", state_01.to_xml_attrs().trim());
1846 println!(" ├── (1,0): {}", state_10.to_xml_attrs().trim());
1847 println!(" └── (2,0): {}", state_20.to_xml_attrs().trim());
1848
1849 // Build the table with REAL merge attributes (gridSpan, rowSpan, hMerge, vMerge)
1850 let merge_table = TableBuilder::new(vec![1500000, 2000000, 2000000, 2000000])
1851 .add_row(TableRow::new(vec![
1852 TableCell::new("Q1 2025 Revenue Report")
1853 .bold()
1854 .background_color("1F4E79")
1855 .text_color("FFFFFF")
1856 .grid_span(4),
1857 TableCell::new("").background_color("1F4E79").h_merge(),
1858 TableCell::new("").background_color("1F4E79").h_merge(),
1859 TableCell::new("").background_color("1F4E79").h_merge(),
1860 ]))
1861 .add_row(TableRow::new(vec![
1862 TableCell::new("Products")
1863 .bold()
1864 .background_color("BDD7EE")
1865 .text_color("1F497D")
1866 .row_span(2),
1867 TableCell::new("Hardware").background_color("E2EFDA"),
1868 TableCell::new("$450,000")
1869 .text_color("2E7D32")
1870 .align_right(),
1871 TableCell::new("+12%")
1872 .bold()
1873 .text_color("2E7D32")
1874 .align_right(),
1875 ]))
1876 .add_row(TableRow::new(vec![
1877 TableCell::new("").background_color("BDD7EE").v_merge(),
1878 TableCell::new("Software").background_color("E2EFDA"),
1879 TableCell::new("$680,000")
1880 .text_color("2E7D32")
1881 .align_right(),
1882 TableCell::new("+25%")
1883 .bold()
1884 .text_color("2E7D32")
1885 .align_right(),
1886 ]))
1887 .add_row(TableRow::new(vec![
1888 TableCell::new("Services")
1889 .bold()
1890 .background_color("FCE4D6")
1891 .text_color("C65911")
1892 .row_span(2),
1893 TableCell::new("Consulting").background_color("FFF2CC"),
1894 TableCell::new("$320,000")
1895 .text_color("2E7D32")
1896 .align_right(),
1897 TableCell::new("+8%")
1898 .bold()
1899 .text_color("2E7D32")
1900 .align_right(),
1901 ]))
1902 .add_row(TableRow::new(vec![
1903 TableCell::new("").background_color("FCE4D6").v_merge(),
1904 TableCell::new("Support").background_color("FFF2CC"),
1905 TableCell::new("$190,000")
1906 .text_color("2E7D32")
1907 .align_right(),
1908 TableCell::new("+5%")
1909 .bold()
1910 .text_color("2E7D32")
1911 .align_right(),
1912 ]))
1913 .position(300000, 1600000)
1914 .build();
1915
1916 // Legend shapes
1917 let legend_anchor = rounded_rect(0.3, 4.8, 2.2, 0.4)
1918 .fill(hex("4472C4"))
1919 .text("Anchor (gridSpan/rowSpan)");
1920 let legend_hmerge = rounded_rect(2.7, 4.8, 2.2, 0.4)
1921 .fill(hex("ED7D31"))
1922 .text("hMerge (col covered)");
1923 let legend_vmerge = rounded_rect(5.1, 4.8, 2.2, 0.4)
1924 .fill(hex("70AD47"))
1925 .text("vMerge (row covered)");
1926 let legend_normal = rounded_rect(7.5, 4.8, 2.2, 0.4)
1927 .fill(hex("A5A5A5"))
1928 .text("Normal (no merge)");
1929
1930 slides.push(
1931 SlideContent::new("Advanced Table Merging - Merged Cells")
1932 .table(merge_table)
1933 .add_shape(legend_anchor)
1934 .add_shape(legend_hmerge)
1935 .add_shape(legend_vmerge)
1936 .add_shape(legend_normal)
1937 .title_color("1F497D")
1938 .title_bold(true),
1939 );
1940
1941 // =========================================================================
1942 // Build PresentationSettings with all advanced features
1943 // =========================================================================
1944 println!("\n⚙️ Building Presentation Settings...");
1945
1946 // Slide show settings (embedded in presProps.xml as <p:showPr>)
1947 let show_settings = SlideShowSettings::new()
1948 .show_type(ShowType::Speaker)
1949 .pen_color(PenColor::red())
1950 .use_timings(true);
1951 println!(" ├── Slide Show: Speaker mode, red pen, timings enabled");
1952 println!(" │ └── XML: {} bytes", show_settings.to_xml().len());
1953
1954 // Print settings (embedded in presProps.xml as <p:prnPr>)
1955 let print_settings = PrintSettings::new()
1956 .print_what(PrintWhat::Handouts)
1957 .color_mode(PrintColorMode::Grayscale)
1958 .handout_layout(GenHandoutLayout::SlidesPerPage6)
1959 .frame_slides(true)
1960 .header("Q1 2025 Strategy Review")
1961 .footer("Confidential - Internal Use Only")
1962 .print_date(true)
1963 .print_page_numbers(true);
1964 println!(" └── Print: Handouts, 6/page, grayscale, framed");
1965 println!(
1966 " └── XML: {} bytes",
1967 print_settings.to_prnpr_xml().len()
1968 );
1969
1970 let pres_settings = PresentationSettings::new()
1971 .slide_show(show_settings)
1972 .print(print_settings);
1973 println!(" All settings configured → presProps.xml");
1974
1975 // =========================================================================
1976 // Generate PPTX with real integrated features
1977 // =========================================================================
1978 println!("\n📦 Generating PPTX with integrated features...");
1979 let pptx_data = create_pptx_with_settings(
1980 "PPTX-RS Element Showcase",
1981 slides.clone(),
1982 Some(pres_settings),
1983 )?;
1984 fs::write("comprehensive_demo.pptx", &pptx_data)?;
1985 println!(
1986 " ✓ Created comprehensive_demo.pptx ({} slides, {} bytes)",
1987 slides.len(),
1988 pptx_data.len()
1989 );
1990
1991 // =========================================================================
1992 // Package Analysis - Demonstrate Reading
1993 // =========================================================================
1994 println!("\n📖 Package Analysis (Read Capability):");
1995
1996 let package = Package::open("comprehensive_demo.pptx")?;
1997 let paths = package.part_paths();
1998
1999 let slide_count = paths
2000 .iter()
2001 .filter(|p| p.starts_with("ppt/slides/slide") && p.ends_with(".xml"))
2002 .count();
2003
2004 println!(" ├── Total parts: {}", package.part_count());
2005 println!(" ├── Slides: {}", slide_count);
2006 println!(" └── Package opened and analyzed successfully");
2007
2008 // =========================================================================
2009 // NEW: Parts API Demonstration
2010 // =========================================================================
2011 println!("\n🧩 Parts API Demonstration:");
2012
2013 // SlideLayoutPart - 11 layout types
2014 println!(" ┌── SlideLayoutPart (11 layout types):");
2015 let layouts = [
2016 LayoutType::Title,
2017 LayoutType::TitleAndContent,
2018 LayoutType::SectionHeader,
2019 LayoutType::TwoContent,
2020 LayoutType::Comparison,
2021 LayoutType::TitleOnly,
2022 LayoutType::Blank,
2023 LayoutType::ContentWithCaption,
2024 LayoutType::PictureWithCaption,
2025 LayoutType::TitleAndVerticalText,
2026 LayoutType::VerticalTitleAndText,
2027 ];
2028 for (i, layout_type) in layouts.iter().enumerate() {
2029 let layout = SlideLayoutPart::new(i + 1, *layout_type);
2030 if i < 3 {
2031 println!(
2032 " │ ├── {}: {} ({})",
2033 i + 1,
2034 layout_type.name(),
2035 layout.path()
2036 );
2037 }
2038 }
2039 println!(" │ └── ... and {} more layout types", layouts.len() - 3);
2040
2041 // SlideMasterPart
2042 println!(" ├── SlideMasterPart:");
2043 let mut master = SlideMasterPart::new(1);
2044 master.set_name("Custom Master");
2045 master.add_layout_rel_id("rId2");
2046 master.add_layout_rel_id("rId3");
2047 println!(" │ ├── Name: {}", master.name());
2048 println!(" │ ├── Path: {}", master.path());
2049 println!(
2050 " │ └── Layouts: {} linked",
2051 master.layout_rel_ids().len()
2052 );
2053
2054 // ThemePart - Colors and Fonts
2055 println!(" ├── ThemePart (colors & fonts):");
2056 let mut theme = ThemePart::new(1);
2057 theme.set_name("Corporate Theme");
2058 theme.set_major_font("Arial");
2059 theme.set_minor_font("Calibri");
2060 theme.set_color("accent1", "FF5733");
2061 theme.set_color("accent2", "33FF57");
2062 let theme_xml = theme.to_xml()?;
2063 println!(" │ ├── Name: {}", theme.name());
2064 println!(" │ ├── Major Font: Arial");
2065 println!(" │ ├── Minor Font: Calibri");
2066 println!(" │ └── XML size: {} bytes", theme_xml.len());
2067
2068 // NotesSlidePart - Speaker notes
2069 println!(" ├── NotesSlidePart (speaker notes):");
2070 let notes = NotesSlidePart::with_text(
2071 1,
2072 "Remember to:\n- Introduce yourself\n- Explain the agenda\n- Ask for questions",
2073 );
2074 let notes_xml = notes.to_xml()?;
2075 println!(" │ ├── Path: {}", notes.path());
2076 println!(
2077 " │ ├── Text: \"{}...\"",
2078 ¬es.notes_text()[..20.min(notes.notes_text().len())]
2079 );
2080 println!(" │ └── XML size: {} bytes", notes_xml.len());
2081
2082 // AppPropertiesPart - Application metadata
2083 println!(" ├── AppPropertiesPart (metadata):");
2084 let mut app_props = AppPropertiesPart::new();
2085 app_props.set_company("Acme Corporation");
2086 app_props.set_slides(slides.len() as u32);
2087 let app_xml = app_props.to_xml()?;
2088 println!(" │ ├── Company: Acme Corporation");
2089 println!(" │ ├── Slides: {}", slides.len());
2090 println!(" │ └── XML size: {} bytes", app_xml.len());
2091
2092 // MediaPart - Video/Audio formats
2093 println!(" ├── MediaPart (10 media formats):");
2094 println!(" │ ├── Video: mp4, webm, avi, wmv, mov");
2095 println!(" │ ├── Audio: mp3, wav, wma, m4a, ogg");
2096 let sample_media = MediaPart::new(1, MediaFormat::Mp4, vec![0; 100]);
2097 println!(
2098 " │ └── Sample: {} ({})",
2099 sample_media.path(),
2100 sample_media.format().mime_type()
2101 );
2102
2103 // TablePart - Table with formatting
2104 println!(" ├── TablePart (cell formatting):");
2105 let table_part = TablePart::new()
2106 .add_row(TableRowPart::new(vec![
2107 TableCellPart::new("Header 1").bold().background("4472C4"),
2108 TableCellPart::new("Header 2").bold().background("4472C4"),
2109 ]))
2110 .add_row(TableRowPart::new(vec![
2111 TableCellPart::new("Data 1").color("333333"),
2112 TableCellPart::new("Data 2").italic(),
2113 ]))
2114 .position(EMU_PER_INCH, EMU_PER_INCH * 2)
2115 .size(EMU_PER_INCH * 6, EMU_PER_INCH * 2);
2116 let table_xml = table_part.to_slide_xml(10);
2117 println!(" │ ├── Rows: {}", table_part.rows.len());
2118 println!(" │ ├── Features: bold, italic, colors, backgrounds");
2119 println!(" │ └── XML size: {} bytes", table_xml.len());
2120
2121 // ContentTypesPart
2122 println!(" └── ContentTypesPart:");
2123 let mut content_types = ContentTypesPart::new();
2124 content_types.add_presentation();
2125 content_types.add_slide(1);
2126 content_types.add_slide_layout(1);
2127 content_types.add_slide_master(1);
2128 content_types.add_theme(1);
2129 content_types.add_core_properties();
2130 content_types.add_app_properties();
2131 let ct_xml = content_types.to_xml()?;
2132 println!(" ├── Path: {}", content_types.path());
2133 println!(" └── XML size: {} bytes", ct_xml.len());
2134
2135 // =========================================================================
2136 // NEW: Elements API Demonstration
2137 // =========================================================================
2138 println!("\n🎨 Elements API Demonstration:");
2139
2140 // Color types
2141 println!(" ┌── Color Types:");
2142 let rgb = RgbColor::new(255, 87, 51);
2143 let rgb_hex = RgbColor::from_hex("#4472C4").unwrap();
2144 let scheme = SchemeColor::Accent1;
2145 let color = Color::rgb(100, 149, 237);
2146 println!(" │ ├── RgbColor::new(255, 87, 51) → {}", rgb.to_hex());
2147 println!(
2148 " │ ├── RgbColor::from_hex(\"#4472C4\") → {}",
2149 rgb_hex.to_hex()
2150 );
2151 println!(" │ ├── SchemeColor::Accent1 → {}", scheme.as_str());
2152 println!(
2153 " │ └── Color::rgb(100, 149, 237) → XML: {}",
2154 color.to_xml().chars().take(30).collect::<String>()
2155 );
2156
2157 // Position and Size
2158 println!(" ├── Position & Size (EMU units):");
2159 let pos = Position::from_inches(1.0, 2.0);
2160 let size = Size::from_inches(4.0, 3.0);
2161 println!(
2162 " │ ├── Position::from_inches(1.0, 2.0) → x={}, y={}",
2163 pos.x, pos.y
2164 );
2165 println!(
2166 " │ ├── Size::from_inches(4.0, 3.0) → w={}, h={}",
2167 size.width, size.height
2168 );
2169 println!(" │ └── EMU_PER_INCH = {}", EMU_PER_INCH);
2170
2171 // Transform
2172 println!(" └── Transform (position + size + rotation):");
2173 let transform = Transform::from_inches(1.0, 1.5, 3.0, 2.0).with_rotation(45.0);
2174 let transform_xml = transform.to_xml();
2175 println!(" ├── Transform::from_inches(1.0, 1.5, 3.0, 2.0)");
2176 println!(" ├── .with_rotation(45.0)");
2177 println!(
2178 " └── XML: {}...",
2179 &transform_xml[..50.min(transform_xml.len())]
2180 );
2181
2182 // =========================================================================
2183 // NEW: Advanced Features Demonstration
2184 // =========================================================================
2185 println!("\n🚀 Advanced Features Demonstration:");
2186
2187 // -------------------------------------------------------------------------
2188 // Complex Table Examples
2189 // -------------------------------------------------------------------------
2190 println!(" ┌── Complex Table Examples:");
2191
2192 // Example 1: Financial Report Table
2193 println!(" │ ┌── Financial Report Table (5x4 with formatting):");
2194 let financial_table = TablePart::new()
2195 .add_row(TableRowPart::new(vec![TableCellPart::new(
2196 "Q1 2024 Financial Summary",
2197 )
2198 .col_span(4)
2199 .bold()
2200 .center()
2201 .background("1F4E79")
2202 .color("FFFFFF")
2203 .font_size(14)
2204 .font("Arial Black")]))
2205 .add_row(TableRowPart::new(vec![
2206 TableCellPart::new("Category")
2207 .bold()
2208 .center()
2209 .background("2E75B6")
2210 .color("FFFFFF"),
2211 TableCellPart::new("Revenue")
2212 .bold()
2213 .center()
2214 .background("2E75B6")
2215 .color("FFFFFF"),
2216 TableCellPart::new("Expenses")
2217 .bold()
2218 .center()
2219 .background("2E75B6")
2220 .color("FFFFFF"),
2221 TableCellPart::new("Profit")
2222 .bold()
2223 .center()
2224 .background("2E75B6")
2225 .color("FFFFFF"),
2226 ]))
2227 .add_row(TableRowPart::new(vec![
2228 TableCellPart::new("Product Sales").align(HorizontalAlign::Left),
2229 TableCellPart::new("$1,250,000")
2230 .align(HorizontalAlign::Right)
2231 .color("2E7D32"),
2232 TableCellPart::new("$450,000")
2233 .align(HorizontalAlign::Right)
2234 .color("C62828"),
2235 TableCellPart::new("$800,000")
2236 .align(HorizontalAlign::Right)
2237 .bold()
2238 .color("2E7D32"),
2239 ]))
2240 .add_row(TableRowPart::new(vec![
2241 TableCellPart::new("Services").align(HorizontalAlign::Left),
2242 TableCellPart::new("$890,000")
2243 .align(HorizontalAlign::Right)
2244 .color("2E7D32"),
2245 TableCellPart::new("$320,000")
2246 .align(HorizontalAlign::Right)
2247 .color("C62828"),
2248 TableCellPart::new("$570,000")
2249 .align(HorizontalAlign::Right)
2250 .bold()
2251 .color("2E7D32"),
2252 ]))
2253 .add_row(TableRowPart::new(vec![
2254 TableCellPart::new("Total").bold().background("E7E6E6"),
2255 TableCellPart::new("$2,140,000")
2256 .bold()
2257 .align(HorizontalAlign::Right)
2258 .background("E7E6E6"),
2259 TableCellPart::new("$770,000")
2260 .bold()
2261 .align(HorizontalAlign::Right)
2262 .background("E7E6E6"),
2263 TableCellPart::new("$1,370,000")
2264 .bold()
2265 .align(HorizontalAlign::Right)
2266 .background("C6EFCE")
2267 .color("006100"),
2268 ]))
2269 .position(EMU_PER_INCH / 2, EMU_PER_INCH * 2)
2270 .size(EMU_PER_INCH * 8, EMU_PER_INCH * 3);
2271 let fin_xml = financial_table.to_slide_xml(100);
2272 println!(" │ │ ├── Merged header spanning 4 columns");
2273 println!(" │ │ ├── Color-coded values (green=positive, red=negative)");
2274 println!(" │ │ ├── Custom fonts and sizes");
2275 println!(" │ │ └── XML: {} bytes", fin_xml.len());
2276
2277 // Example 2: Comparison Matrix
2278 println!(" │ ├── Comparison Matrix (features vs products):");
2279 let _matrix_table = TablePart::new()
2280 .add_row(TableRowPart::new(vec![
2281 TableCellPart::new("Feature")
2282 .bold()
2283 .center()
2284 .background("4472C4")
2285 .color("FFFFFF"),
2286 TableCellPart::new("Basic")
2287 .bold()
2288 .center()
2289 .background("4472C4")
2290 .color("FFFFFF"),
2291 TableCellPart::new("Pro")
2292 .bold()
2293 .center()
2294 .background("4472C4")
2295 .color("FFFFFF"),
2296 TableCellPart::new("Enterprise")
2297 .bold()
2298 .center()
2299 .background("4472C4")
2300 .color("FFFFFF"),
2301 ]))
2302 .add_row(TableRowPart::new(vec![
2303 TableCellPart::new("Storage").align(HorizontalAlign::Left),
2304 TableCellPart::new("5 GB").center(),
2305 TableCellPart::new("50 GB").center(),
2306 TableCellPart::new("Unlimited")
2307 .center()
2308 .bold()
2309 .color("2E7D32"),
2310 ]))
2311 .add_row(TableRowPart::new(vec![
2312 TableCellPart::new("Users").align(HorizontalAlign::Left),
2313 TableCellPart::new("1").center(),
2314 TableCellPart::new("10").center(),
2315 TableCellPart::new("Unlimited")
2316 .center()
2317 .bold()
2318 .color("2E7D32"),
2319 ]))
2320 .add_row(TableRowPart::new(vec![
2321 TableCellPart::new("Support").align(HorizontalAlign::Left),
2322 TableCellPart::new("Email").center(),
2323 TableCellPart::new("24/7 Chat").center(),
2324 TableCellPart::new("Dedicated")
2325 .center()
2326 .bold()
2327 .color("2E7D32"),
2328 ]))
2329 .add_row(TableRowPart::new(vec![
2330 TableCellPart::new("Price/mo").bold().background("F2F2F2"),
2331 TableCellPart::new("$9")
2332 .center()
2333 .bold()
2334 .background("F2F2F2"),
2335 TableCellPart::new("$29")
2336 .center()
2337 .bold()
2338 .background("F2F2F2"),
2339 TableCellPart::new("$99")
2340 .center()
2341 .bold()
2342 .background("F2F2F2"),
2343 ]));
2344 println!(" │ │ └── 5x4 matrix with alternating styles");
2345
2346 // Example 3: Schedule/Timeline Table
2347 println!(" │ └── Schedule Table (with row spans):");
2348 let _schedule_table = TablePart::new()
2349 .add_row(TableRowPart::new(vec![
2350 TableCellPart::new("Time")
2351 .bold()
2352 .center()
2353 .background("70AD47")
2354 .color("FFFFFF"),
2355 TableCellPart::new("Monday")
2356 .bold()
2357 .center()
2358 .background("70AD47")
2359 .color("FFFFFF"),
2360 TableCellPart::new("Tuesday")
2361 .bold()
2362 .center()
2363 .background("70AD47")
2364 .color("FFFFFF"),
2365 ]))
2366 .add_row(TableRowPart::new(vec![
2367 TableCellPart::new("9:00 AM").center().background("E2EFDA"),
2368 TableCellPart::new("Team Standup")
2369 .center()
2370 .row_span(2)
2371 .valign(VerticalAlign::Middle)
2372 .background("BDD7EE"),
2373 TableCellPart::new("Code Review").center(),
2374 ]))
2375 .add_row(TableRowPart::new(vec![
2376 TableCellPart::new("10:00 AM").center().background("E2EFDA"),
2377 TableCellPart::merged(),
2378 TableCellPart::new("Sprint Planning")
2379 .center()
2380 .background("FCE4D6"),
2381 ]));
2382 println!(" │ └── Row spans for multi-hour events");
2383
2384 println!(" ├── (Animation/SmartArt/3D/VBA/CustomXml/EmbeddedFont/Handout removed in lean refactor)");
2385
2386 // -------------------------------------------------------------------------
2387 // Theme + Master + Layout Combination
2388 // -------------------------------------------------------------------------
2389 println!(" ├── Theme + Master + Layout Integration:");
2390
2391 // Corporate theme
2392 let mut corp_theme = ThemePart::new(1);
2393 corp_theme.set_name("Corporate Blue");
2394 corp_theme.set_major_font("Segoe UI");
2395 corp_theme.set_minor_font("Segoe UI Light");
2396 corp_theme.set_color("dk1", "000000");
2397 corp_theme.set_color("lt1", "FFFFFF");
2398 corp_theme.set_color("dk2", "1F497D");
2399 corp_theme.set_color("lt2", "EEECE1");
2400 corp_theme.set_color("accent1", "4472C4");
2401 corp_theme.set_color("accent2", "ED7D31");
2402 corp_theme.set_color("accent3", "A5A5A5");
2403 corp_theme.set_color("accent4", "FFC000");
2404 corp_theme.set_color("accent5", "5B9BD5");
2405 corp_theme.set_color("accent6", "70AD47");
2406 let theme_xml = corp_theme.to_xml()?;
2407 println!(" │ ├── Theme: Corporate Blue");
2408 println!(" │ │ ├── Fonts: Segoe UI / Segoe UI Light");
2409 println!(" │ │ ├── 12 color slots defined");
2410 println!(" │ │ └── XML: {} bytes", theme_xml.len());
2411
2412 // Master with multiple layouts
2413 let mut corp_master = SlideMasterPart::new(1);
2414 corp_master.set_name("Corporate Master");
2415 corp_master.add_layout_rel_id("rId2"); // Title
2416 corp_master.add_layout_rel_id("rId3"); // Title + Content
2417 corp_master.add_layout_rel_id("rId4"); // Section Header
2418 corp_master.add_layout_rel_id("rId5"); // Two Content
2419 corp_master.add_layout_rel_id("rId6"); // Comparison
2420 corp_master.add_layout_rel_id("rId7"); // Title Only
2421 corp_master.add_layout_rel_id("rId8"); // Blank
2422 println!(
2423 " │ └── Master: {} with {} layouts linked",
2424 corp_master.name(),
2425 corp_master.layout_rel_ids().len()
2426 );
2427
2428 println!(" ├── Theme + Master + Layout Integration:");
2429 println!("\n╔══════════════════════════════════════════════════════════════╗");
2430 println!("║ Element Coverage Summary ║");
2431 println!("╠══════════════════════════════════════════════════════════════╣");
2432 println!("║ LAYOUTS (6 types): ║");
2433 println!("║ ✓ CenteredTitle ✓ TitleOnly ✓ TitleAndContent ║");
2434 println!("║ ✓ TitleAndBigContent ✓ TwoColumn ✓ Blank ║");
2435 println!("╠══════════════════════════════════════════════════════════════╣");
2436 println!("║ TEXT FORMATTING: ║");
2437 println!("║ ✓ Bold ✓ Italic ✓ Underline ║");
2438 println!("║ ✓ Font Size ✓ Font Color ✓ Title/Content styles ║");
2439 println!("╠══════════════════════════════════════════════════════════════╣");
2440 println!("║ TABLES: ║");
2441 println!("║ ✓ Multiple rows/columns ✓ Bold cells ✓ Background colors║");
2442 println!("║ ✓ Header styling ✓ Position control ║");
2443 println!("╠══════════════════════════════════════════════════════════════╣");
2444 println!("║ CHARTS: ║");
2445 println!("║ ✓ Bar Chart ✓ Line Chart ✓ Pie Chart ║");
2446 println!("║ ✓ Multiple series ✓ Categories ║");
2447 println!("╠══════════════════════════════════════════════════════════════╣");
2448 println!("║ SHAPES: ║");
2449 println!("║ ✓ Rectangle ✓ Ellipse ✓ RoundedRectangle ║");
2450 println!("║ ✓ Triangle ✓ Diamond ✓ Color fills ║");
2451 println!("║ ✓ Gradient fills ✓ Transparency ✓ Text in shapes ║");
2452 println!("╠══════════════════════════════════════════════════════════════╣");
2453 println!("║ CONNECTORS (NEW): ║");
2454 println!("║ ✓ Straight ✓ Elbow ✓ Curved ║");
2455 println!("║ ✓ Arrow types ✓ Dash styles ✓ Line colors/widths ║");
2456 println!("╠══════════════════════════════════════════════════════════════╣");
2457 println!("║ IMAGES: ║");
2458 println!("║ ✓ Image placeholders ✓ Position ✓ Dimensions ║");
2459 println!("╠══════════════════════════════════════════════════════════════╣");
2460 println!("║ PACKAGE: ║");
2461 println!("║ ✓ Create PPTX ✓ Read PPTX ✓ Analyze contents ║");
2462 println!("╠══════════════════════════════════════════════════════════════╣");
2463 println!("║ PARTS API (NEW): ║");
2464 println!("║ ✓ SlideLayoutPart (11 types) ✓ SlideMasterPart ║");
2465 println!("║ ✓ ThemePart (colors/fonts) ✓ NotesSlidePart ║");
2466 println!("║ ✓ AppPropertiesPart ✓ MediaPart (10 formats) ║");
2467 println!("║ ✓ TablePart (cell formatting) ✓ ContentTypesPart ║");
2468 println!("╠══════════════════════════════════════════════════════════════╣");
2469 println!("║ ELEMENTS API: ║");
2470 println!("║ ✓ RgbColor ✓ SchemeColor ✓ Color enum ║");
2471 println!("║ ✓ Position ✓ Size ✓ Transform ║");
2472 println!("║ ✓ EMU conversions (inches, cm, mm, pt) ║");
2473 println!("╠══════════════════════════════════════════════════════════════╣");
2474 println!("║ ADVANCED FEATURES: ║");
2475 println!("║ ✓ Table borders/alignment ✓ Merged cells ║");
2476 println!("╠══════════════════════════════════════════════════════════════╣");
2477 println!("║ DIMENSION API (NEW): ║");
2478 println!("║ ✓ EMU / Inches / Cm / Pt / Ratio / Percent units ║");
2479 println!("║ ✓ from_dimensions() constructor ║");
2480 println!("║ ✓ Fluent .at() and .with_dimensions() chaining ║");
2481 println!("║ ✓ Mixed-unit positioning (e.g. inches + percent) ║");
2482 println!("╠══════════════════════════════════════════════════════════════╣");
2483 println!(
2484 "║ Output: comprehensive_demo.pptx ({} slides, {} KB) ║",
2485 slides.len(),
2486 pptx_data.len() / 1024
2487 );
2488 println!("╚══════════════════════════════════════════════════════════════╝");
2489
2490 Ok(())
2491}Sourcepub fn with_col_span(self, span: u32) -> Self
pub fn with_col_span(self, span: u32) -> Self
Alias: set column span (gridSpan)
Sourcepub fn with_row_span(self, span: u32) -> Self
pub fn with_row_span(self, span: u32) -> Self
Alias: set row span
Sourcepub fn with_h_merge(self) -> Self
pub fn with_h_merge(self) -> Self
Alias: set horizontal merge flag
Sourcepub fn with_v_merge(self) -> Self
pub fn with_v_merge(self) -> Self
Alias: set vertical merge flag