1use ppt_rs::generator::{
7 Shape, ShapeType, ShapeFill, ShapeLine,
8 generate_shape_xml, generate_shapes_xml, generate_connector_xml,
9 inches_to_emu, cm_to_emu,
10};
11use ppt_rs::core::Dimension;
12
13fn main() {
14 println!("╔════════════════════════════════════════════════════════════╗");
15 println!("║ PPTX Shapes Demo ║");
16 println!("╚════════════════════════════════════════════════════════════╝\n");
17
18 println!("📐 Basic Shapes:");
22
23 let basic_shapes = [
24 ShapeType::Rectangle,
25 ShapeType::RoundedRectangle,
26 ShapeType::Ellipse,
27 ShapeType::Triangle,
28 ShapeType::Diamond,
29 ShapeType::Pentagon,
30 ShapeType::Hexagon,
31 ShapeType::Octagon,
32 ];
33
34 for shape_type in &basic_shapes {
35 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
36 }
37
38 println!("\n➡️ Arrow Shapes:");
42
43 let arrow_shapes = [
44 ShapeType::RightArrow,
45 ShapeType::LeftArrow,
46 ShapeType::UpArrow,
47 ShapeType::DownArrow,
48 ShapeType::LeftRightArrow,
49 ShapeType::UpDownArrow,
50 ];
51
52 for shape_type in &arrow_shapes {
53 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
54 }
55
56 println!("\n⭐ Stars and Banners:");
60
61 let star_shapes = [
62 ShapeType::Star4,
63 ShapeType::Star5,
64 ShapeType::Star6,
65 ShapeType::Star8,
66 ShapeType::Ribbon,
67 ShapeType::Wave,
68 ];
69
70 for shape_type in &star_shapes {
71 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
72 }
73
74 println!("\n💬 Callout Shapes:");
78
79 let callout_shapes = [
80 ShapeType::WedgeRectCallout,
81 ShapeType::WedgeEllipseCallout,
82 ShapeType::CloudCallout,
83 ];
84
85 for shape_type in &callout_shapes {
86 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
87 }
88
89 println!("\n📊 Flow Chart Shapes:");
93
94 let flowchart_shapes = [
95 ShapeType::FlowChartProcess,
96 ShapeType::FlowChartDecision,
97 ShapeType::FlowChartTerminator,
98 ShapeType::FlowChartDocument,
99 ];
100
101 for shape_type in &flowchart_shapes {
102 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
103 }
104
105 println!("\n🎨 Other Shapes:");
109
110 let other_shapes = [
111 ShapeType::Heart,
112 ShapeType::Lightning,
113 ShapeType::Sun,
114 ShapeType::Moon,
115 ShapeType::Cloud,
116 ];
117
118 for shape_type in &other_shapes {
119 println!(" {} → {}", shape_type.display_name(), shape_type.preset_name());
120 }
121
122 println!("\n🎨 Shape with Fill:");
126
127 let filled_shape = Shape::new(
128 ShapeType::Rectangle,
129 inches_to_emu(1.0),
130 inches_to_emu(1.0),
131 inches_to_emu(3.0),
132 inches_to_emu(2.0),
133 ).with_fill(ShapeFill::new("4472C4")); let xml = generate_shape_xml(&filled_shape, 1);
136 println!(" Generated XML ({} chars)", xml.len());
137 println!(" Contains fill: {}", xml.contains("solidFill"));
138
139 println!("\n📏 Shape with Line:");
143
144 let outlined_shape = Shape::new(
145 ShapeType::Ellipse,
146 inches_to_emu(1.0),
147 inches_to_emu(1.0),
148 inches_to_emu(2.0),
149 inches_to_emu(2.0),
150 ).with_line(ShapeLine::new("FF0000", 25400)); let xml = generate_shape_xml(&outlined_shape, 2);
153 println!(" Generated XML ({} chars)", xml.len());
154 println!(" Contains line: {}", xml.contains("a:ln"));
155
156 println!("\n📝 Shape with Text:");
160
161 let text_shape = Shape::new(
162 ShapeType::RoundedRectangle,
163 cm_to_emu(5.0),
164 cm_to_emu(3.0),
165 cm_to_emu(8.0),
166 cm_to_emu(4.0),
167 )
168 .with_fill(ShapeFill::new("70AD47")) .with_text("Click Here!");
170
171 let xml = generate_shape_xml(&text_shape, 3);
172 println!(" Generated XML ({} chars)", xml.len());
173 println!(" Contains text: {}", xml.contains("Click Here!"));
174
175 println!("\n📦 Multiple Shapes:");
179
180 let shapes = vec![
181 Shape::new(ShapeType::Rectangle, 0, 0, 1000000, 500000)
182 .with_fill(ShapeFill::new("FF0000")),
183 Shape::new(ShapeType::Ellipse, 1200000, 0, 500000, 500000)
184 .with_fill(ShapeFill::new("00FF00")),
185 Shape::new(ShapeType::Triangle, 1900000, 0, 500000, 500000)
186 .with_fill(ShapeFill::new("0000FF")),
187 ];
188
189 let xml = generate_shapes_xml(&shapes, 10);
190 println!(" Generated {} shapes", shapes.len());
191 println!(" Total XML: {} chars", xml.len());
192
193 println!("\n🔗 Connector:");
197
198 let connector_xml = generate_connector_xml(
199 0, 0,
200 inches_to_emu(3.0), inches_to_emu(2.0),
201 100,
202 "000000",
203 12700, );
205 println!(" Generated connector XML ({} chars)", connector_xml.len());
206 println!(" Has arrow head: {}", connector_xml.contains("triangle"));
207
208 println!("\n📏 Flexible Dimension API (NEW):");
212
213 let ratio_shape = Shape::from_dimensions(
215 ShapeType::Rectangle,
216 Dimension::Ratio(0.1), Dimension::Ratio(0.2), Dimension::Ratio(0.8), Dimension::Ratio(0.6), ).with_fill(ShapeFill::new("4472C4")).with_text("Ratio-based");
219
220 let xml = generate_shape_xml(&ratio_shape, 20);
221 println!(" Ratio-based shape: {}x{} EMU at ({}, {})",
222 ratio_shape.width, ratio_shape.height, ratio_shape.x, ratio_shape.y);
223 println!(" Generated XML ({} chars)", xml.len());
224
225 let mixed_shape = Shape::from_dimensions(
227 ShapeType::RoundedRectangle,
228 Dimension::Inches(1.0), Dimension::Cm(3.0), Dimension::Ratio(0.5), Dimension::Inches(1.5), ).with_fill(ShapeFill::new("70AD47")).with_text("Mixed units");
231
232 println!(" Mixed-unit shape: {}x{} EMU at ({}, {})",
233 mixed_shape.width, mixed_shape.height, mixed_shape.x, mixed_shape.y);
234
235 let fluent_shape = Shape::new(ShapeType::Ellipse, 0, 0, 0, 0)
237 .at(Dimension::percent(50.0), Dimension::percent(50.0)) .with_dimensions(Dimension::Inches(2.0), Dimension::Inches(2.0))
239 .with_fill(ShapeFill::new("C0504D"))
240 .with_text("Centered");
241
242 println!(" Fluent chained shape: {}x{} EMU at ({}, {})",
243 fluent_shape.width, fluent_shape.height, fluent_shape.x, fluent_shape.y);
244
245 let percent_shape = Shape::from_dimensions(
247 ShapeType::Diamond,
248 Dimension::percent(40.0), Dimension::percent(30.0),
249 Dimension::percent(20.0), Dimension::percent(40.0),
250 ).with_fill(ShapeFill::new("8064A2"));
251
252 println!(" Percent-based shape: {}x{} EMU at ({}, {})",
253 percent_shape.width, percent_shape.height, percent_shape.x, percent_shape.y);
254
255 let pt_shape = Shape::from_dimensions(
257 ShapeType::Rectangle,
258 Dimension::Pt(72.0), Dimension::Pt(72.0), Dimension::Pt(360.0), Dimension::Pt(144.0), ).with_fill(ShapeFill::new("F79646")).with_text("Points");
261
262 println!(" Point-based shape: {}x{} EMU at ({}, {})",
263 pt_shape.width, pt_shape.height, pt_shape.x, pt_shape.y);
264
265 println!("\n Unit equivalence (all = 1 inch = 914400 EMU):");
267 let units = [
268 ("Emu(914400)", Dimension::Emu(914400)),
269 ("Inches(1.0)", Dimension::Inches(1.0)),
270 ("Cm(2.54)", Dimension::Cm(2.54)),
271 ("Pt(72.0)", Dimension::Pt(72.0)),
272 ("Ratio(0.1)", Dimension::Ratio(0.1)), ];
274 for (label, dim) in &units {
275 println!(" {:<16} → {} EMU", label, dim.to_emu_x());
276 }
277
278 println!("\n╔════════════════════════════════════════════════════════════╗");
282 println!("║ Demo Complete ║");
283 println!("╠════════════════════════════════════════════════════════════╣");
284 println!("║ Shape Types Available: 40+ ║");
285 println!("║ Features: ║");
286 println!("║ ✓ Basic shapes (rect, ellipse, triangle, etc.) ║");
287 println!("║ ✓ Arrow shapes (8 directions) ║");
288 println!("║ ✓ Stars and banners ║");
289 println!("║ ✓ Callouts ║");
290 println!("║ ✓ Flow chart shapes ║");
291 println!("║ ✓ Fill colors with transparency ║");
292 println!("║ ✓ Line/border styling ║");
293 println!("║ ✓ Text inside shapes ║");
294 println!("║ ✓ Connectors with arrow heads ║");
295 println!("║ ✓ NEW: Flexible Dimension API (EMU/inches/cm/pt/ratio) ║");
296 println!("║ ✓ NEW: Fluent .at() and .with_dimensions() chaining ║");
297 println!("║ ✓ NEW: Percent-based positioning ║");
298 println!("╚════════════════════════════════════════════════════════════╝");
299}