pub struct RgbColor {
pub r: u8,
pub g: u8,
pub b: u8,
}Expand description
RGB color (6-digit hex)
Fields§
§r: u8§g: u8§b: u8Implementations§
Source§impl RgbColor
impl RgbColor
Sourcepub fn new(r: u8, g: u8, b: u8) -> Self
pub fn new(r: u8, g: u8, b: u8) -> Self
Create a new RGB color
Examples found in repository?
examples/comprehensive_demo.rs (line 2142)
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 from_hex(hex: &str) -> Option<Self>
pub fn from_hex(hex: &str) -> Option<Self>
Parse from hex string (e.g., “FF0000” or “#FF0000”)
Examples found in repository?
examples/comprehensive_demo.rs (line 2143)
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 to_hex(&self) -> String
pub fn to_hex(&self) -> String
Convert to hex string (uppercase, no #)
Examples found in repository?
examples/comprehensive_demo.rs (line 2146)
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}pub fn white() -> Self
pub fn red() -> Self
pub fn green() -> Self
pub fn blue() -> Self
Trait Implementations§
impl Eq for RgbColor
impl StructuralPartialEq for RgbColor
Auto Trait Implementations§
impl Freeze for RgbColor
impl RefUnwindSafe for RgbColor
impl Send for RgbColor
impl Sync for RgbColor
impl Unpin for RgbColor
impl UnsafeUnpin for RgbColor
impl UnwindSafe for RgbColor
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more