pub struct ShapeGroup {
pub id: u32,
pub name: String,
pub offset_emu: (i64, i64),
pub extent_emu: (i64, i64),
pub child_offset_emu: (i64, i64),
pub child_extent_emu: (i64, i64),
pub rotation_60000ths: i32,
pub flip_horizontal: bool,
pub flip_vertical: bool,
pub shapes: Vec<Shape>,
}Expand description
A group of shapes moving/resizing together (<p:grpSp>, CT_GroupShape).
A group’s own transform is two coordinate pairs working together, not one:
offset_emu/extent_emu (<a:off>/<a:ext>) place the group on the slide, exactly like any
other shape; child_offset_emu/ child_extent_emu (<a:chOff>/<a:chExt>) define the
coordinate space the children’s own xfrm values are expressed in — real PowerPoint scales
between the two automatically whenever they differ (e.g. a group’s children keep their original
small-scale coordinates while the group itself is stretched much larger on the slide). Confirmed
against a real fixture with nested groups, including a group whose child coordinate space
genuinely differs from its own on-slide extent. Groups can nest (a Shape::Group inside
another’s own shapes), confirmed on the same fixture.
Fields§
§id: u32<p:cNvPr id=".."> — same uniqueness rules as AutoShape::id.
name: String<p:cNvPr name="..">.
offset_emu: (i64, i64)<a:xfrm><a:off x=".." y="..">, in EMUs.
extent_emu: (i64, i64)<a:xfrm><a:ext cx=".." cy="..">, in EMUs.
child_offset_emu: (i64, i64)<a:xfrm><a:chOff x=".." y="..">, in EMUs — the coordinate space this group’s children’s
own xfrm values are expressed in.
child_extent_emu: (i64, i64)<a:xfrm><a:chExt cx=".." cy="..">, in EMUs.
rotation_60000ths: i32<a:xfrm rot="."> — ST_Angle, in 60,000ths of a degree, positive clockwise. 0 (the
default) omits the attribute — no rotation. Symmetric to
drawing::Transform2D::rotation_60000ths. Grounded against real fixtures.
flip_horizontal: bool<a:xfrm flipH="."> — mirrors the whole group horizontally before rotation is applied.
Not grounded on a group specifically in the fixture corpus — modeled by analogy to
drawing::Transform2D::flip_horizontal (identical CT_GroupTransform2D/CT_Transform2D
attribute, already grounded there).
flip_vertical: bool<a:xfrm flipV=".."> — mirrors the whole group vertically. Same grounding caveat as
flip_horizontal.
shapes: Vec<Shape>The group’s children, in document order — any shape kind, including nested groups.
Implementations§
Source§impl ShapeGroup
impl ShapeGroup
Sourcepub fn new(id: u32, name: impl Into<String>) -> ShapeGroup
pub fn new(id: u32, name: impl Into<String>) -> ShapeGroup
Creates an empty group (no children) with a zero-valued transform — use
ShapeGroup::with_transform to position it and its children’s coordinate space, and
ShapeGroup::with_shape to add children.
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("pptx_grouping_and_connectors.pptx");
18
19 // Every shape below sets an explicit fill (and the connector an
20 // explicit line): with neither a fill/line nor a `<p:style>` theme
21 // reference, a shape has nothing to paint and renders as fully
22 // invisible — the slide then looks blank even though the shapes are
23 // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24 // explicit `Fill`/`Line` is the only way to make a shape actually show.
25 let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27 let circle = AutoShape::new(11, "Circle").with_properties(
28 ShapeProperties::new()
29 .with_transform(
30 Transform2D::new()
31 .with_offset(0, 0)
32 .with_extent(1_000_000, 1_000_000),
33 )
34 .with_fill(circle_fill()),
35 );
36 let label = AutoShape::new(12, "Label")
37 .with_properties(
38 ShapeProperties::new()
39 .with_transform(
40 Transform2D::new()
41 .with_offset(1_200_000, 300_000)
42 .with_extent(1_500_000, 400_000),
43 )
44 .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45 )
46 .with_text_body(
47 TextBody::new()
48 .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49 );
50
51 let group = ShapeGroup::new(2, "Group")
52 .with_transform(
53 (838_200, 838_200),
54 (2_700_000, 1_000_000),
55 (0, 0),
56 (2_700_000, 1_000_000),
57 )
58 .with_shape(Shape::AutoShape(circle))
59 .with_shape(Shape::AutoShape(label));
60
61 let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62 ShapeProperties::new()
63 .with_transform(
64 Transform2D::new()
65 .with_offset(0, 0)
66 .with_extent(1_000_000, 1_000_000),
67 )
68 .with_fill(circle_fill()),
69 );
70 let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71 .with_transform(
72 (838_200, 838_200),
73 (1_000_000, 1_000_000),
74 (0, 0),
75 (1_000_000, 1_000_000),
76 )
77 .with_rotation_degrees(45.0)
78 .with_flip_horizontal(true)
79 .with_shape(Shape::AutoShape(rotated_circle));
80
81 let box_a = AutoShape::new(2, "Box A").with_properties(
82 ShapeProperties::new()
83 .with_transform(
84 Transform2D::new()
85 .with_offset(838_200, 838_200)
86 .with_extent(1_000_000, 1_000_000),
87 )
88 .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89 );
90 let box_b = AutoShape::new(3, "Box B").with_properties(
91 ShapeProperties::new()
92 .with_transform(
93 Transform2D::new()
94 .with_offset(3_500_000, 838_200)
95 .with_extent(1_000_000, 1_000_000),
96 )
97 .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98 );
99 // `Connector::new` leaves position/size unset, which the writer then
100 // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101 // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102 // alone don't supply geometry; PowerPoint only recomputes it once you
103 // drag one of the attached shapes. So this also sets an explicit
104 // transform spanning Box A's right edge to Box B's left edge.
105 let connector = Connector::new(4, "Connector")
106 .with_properties(
107 ShapeProperties::new()
108 .with_transform(
109 Transform2D::new()
110 .with_offset(1_838_200, 1_338_200)
111 .with_extent(1_662_000, 0),
112 )
113 .with_line(
114 Line::new()
115 .with_width_emu(25_400)
116 .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117 ),
118 )
119 .with_start_connection(2, 0)
120 .with_end_connection(3, 0);
121
122 let presentation = Presentation::new()
123 .with_slide(Slide::new().with_shape(Shape::Group(group)))
124 .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125 .with_slide(
126 Slide::new()
127 .with_shape(Shape::AutoShape(box_a))
128 .with_shape(Shape::AutoShape(box_b))
129 .with_shape(Shape::Connector(connector)),
130 );
131
132 presentation.save_to_file(&path)?;
133 println!("Wrote {}", path.display());
134 Ok(())
135}Sourcepub fn with_transform(
self,
offset_emu: (i64, i64),
extent_emu: (i64, i64),
child_offset_emu: (i64, i64),
child_extent_emu: (i64, i64),
) -> ShapeGroup
pub fn with_transform( self, offset_emu: (i64, i64), extent_emu: (i64, i64), child_offset_emu: (i64, i64), child_extent_emu: (i64, i64), ) -> ShapeGroup
Sets this group’s own on-slide position/size and its children’s coordinate space (often the same values, when no scaling between the two is needed).
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("pptx_grouping_and_connectors.pptx");
18
19 // Every shape below sets an explicit fill (and the connector an
20 // explicit line): with neither a fill/line nor a `<p:style>` theme
21 // reference, a shape has nothing to paint and renders as fully
22 // invisible — the slide then looks blank even though the shapes are
23 // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24 // explicit `Fill`/`Line` is the only way to make a shape actually show.
25 let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27 let circle = AutoShape::new(11, "Circle").with_properties(
28 ShapeProperties::new()
29 .with_transform(
30 Transform2D::new()
31 .with_offset(0, 0)
32 .with_extent(1_000_000, 1_000_000),
33 )
34 .with_fill(circle_fill()),
35 );
36 let label = AutoShape::new(12, "Label")
37 .with_properties(
38 ShapeProperties::new()
39 .with_transform(
40 Transform2D::new()
41 .with_offset(1_200_000, 300_000)
42 .with_extent(1_500_000, 400_000),
43 )
44 .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45 )
46 .with_text_body(
47 TextBody::new()
48 .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49 );
50
51 let group = ShapeGroup::new(2, "Group")
52 .with_transform(
53 (838_200, 838_200),
54 (2_700_000, 1_000_000),
55 (0, 0),
56 (2_700_000, 1_000_000),
57 )
58 .with_shape(Shape::AutoShape(circle))
59 .with_shape(Shape::AutoShape(label));
60
61 let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62 ShapeProperties::new()
63 .with_transform(
64 Transform2D::new()
65 .with_offset(0, 0)
66 .with_extent(1_000_000, 1_000_000),
67 )
68 .with_fill(circle_fill()),
69 );
70 let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71 .with_transform(
72 (838_200, 838_200),
73 (1_000_000, 1_000_000),
74 (0, 0),
75 (1_000_000, 1_000_000),
76 )
77 .with_rotation_degrees(45.0)
78 .with_flip_horizontal(true)
79 .with_shape(Shape::AutoShape(rotated_circle));
80
81 let box_a = AutoShape::new(2, "Box A").with_properties(
82 ShapeProperties::new()
83 .with_transform(
84 Transform2D::new()
85 .with_offset(838_200, 838_200)
86 .with_extent(1_000_000, 1_000_000),
87 )
88 .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89 );
90 let box_b = AutoShape::new(3, "Box B").with_properties(
91 ShapeProperties::new()
92 .with_transform(
93 Transform2D::new()
94 .with_offset(3_500_000, 838_200)
95 .with_extent(1_000_000, 1_000_000),
96 )
97 .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98 );
99 // `Connector::new` leaves position/size unset, which the writer then
100 // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101 // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102 // alone don't supply geometry; PowerPoint only recomputes it once you
103 // drag one of the attached shapes. So this also sets an explicit
104 // transform spanning Box A's right edge to Box B's left edge.
105 let connector = Connector::new(4, "Connector")
106 .with_properties(
107 ShapeProperties::new()
108 .with_transform(
109 Transform2D::new()
110 .with_offset(1_838_200, 1_338_200)
111 .with_extent(1_662_000, 0),
112 )
113 .with_line(
114 Line::new()
115 .with_width_emu(25_400)
116 .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117 ),
118 )
119 .with_start_connection(2, 0)
120 .with_end_connection(3, 0);
121
122 let presentation = Presentation::new()
123 .with_slide(Slide::new().with_shape(Shape::Group(group)))
124 .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125 .with_slide(
126 Slide::new()
127 .with_shape(Shape::AutoShape(box_a))
128 .with_shape(Shape::AutoShape(box_b))
129 .with_shape(Shape::Connector(connector)),
130 );
131
132 presentation.save_to_file(&path)?;
133 println!("Wrote {}", path.display());
134 Ok(())
135}Sourcepub fn with_rotation_degrees(self, degrees: f64) -> ShapeGroup
pub fn with_rotation_degrees(self, degrees: f64) -> ShapeGroup
Sets this group’s rotation, given in ordinary degrees (converted to the schema’s 60,000ths-of-a-degree unit internally).
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("pptx_grouping_and_connectors.pptx");
18
19 // Every shape below sets an explicit fill (and the connector an
20 // explicit line): with neither a fill/line nor a `<p:style>` theme
21 // reference, a shape has nothing to paint and renders as fully
22 // invisible — the slide then looks blank even though the shapes are
23 // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24 // explicit `Fill`/`Line` is the only way to make a shape actually show.
25 let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27 let circle = AutoShape::new(11, "Circle").with_properties(
28 ShapeProperties::new()
29 .with_transform(
30 Transform2D::new()
31 .with_offset(0, 0)
32 .with_extent(1_000_000, 1_000_000),
33 )
34 .with_fill(circle_fill()),
35 );
36 let label = AutoShape::new(12, "Label")
37 .with_properties(
38 ShapeProperties::new()
39 .with_transform(
40 Transform2D::new()
41 .with_offset(1_200_000, 300_000)
42 .with_extent(1_500_000, 400_000),
43 )
44 .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45 )
46 .with_text_body(
47 TextBody::new()
48 .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49 );
50
51 let group = ShapeGroup::new(2, "Group")
52 .with_transform(
53 (838_200, 838_200),
54 (2_700_000, 1_000_000),
55 (0, 0),
56 (2_700_000, 1_000_000),
57 )
58 .with_shape(Shape::AutoShape(circle))
59 .with_shape(Shape::AutoShape(label));
60
61 let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62 ShapeProperties::new()
63 .with_transform(
64 Transform2D::new()
65 .with_offset(0, 0)
66 .with_extent(1_000_000, 1_000_000),
67 )
68 .with_fill(circle_fill()),
69 );
70 let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71 .with_transform(
72 (838_200, 838_200),
73 (1_000_000, 1_000_000),
74 (0, 0),
75 (1_000_000, 1_000_000),
76 )
77 .with_rotation_degrees(45.0)
78 .with_flip_horizontal(true)
79 .with_shape(Shape::AutoShape(rotated_circle));
80
81 let box_a = AutoShape::new(2, "Box A").with_properties(
82 ShapeProperties::new()
83 .with_transform(
84 Transform2D::new()
85 .with_offset(838_200, 838_200)
86 .with_extent(1_000_000, 1_000_000),
87 )
88 .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89 );
90 let box_b = AutoShape::new(3, "Box B").with_properties(
91 ShapeProperties::new()
92 .with_transform(
93 Transform2D::new()
94 .with_offset(3_500_000, 838_200)
95 .with_extent(1_000_000, 1_000_000),
96 )
97 .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98 );
99 // `Connector::new` leaves position/size unset, which the writer then
100 // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101 // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102 // alone don't supply geometry; PowerPoint only recomputes it once you
103 // drag one of the attached shapes. So this also sets an explicit
104 // transform spanning Box A's right edge to Box B's left edge.
105 let connector = Connector::new(4, "Connector")
106 .with_properties(
107 ShapeProperties::new()
108 .with_transform(
109 Transform2D::new()
110 .with_offset(1_838_200, 1_338_200)
111 .with_extent(1_662_000, 0),
112 )
113 .with_line(
114 Line::new()
115 .with_width_emu(25_400)
116 .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117 ),
118 )
119 .with_start_connection(2, 0)
120 .with_end_connection(3, 0);
121
122 let presentation = Presentation::new()
123 .with_slide(Slide::new().with_shape(Shape::Group(group)))
124 .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125 .with_slide(
126 Slide::new()
127 .with_shape(Shape::AutoShape(box_a))
128 .with_shape(Shape::AutoShape(box_b))
129 .with_shape(Shape::Connector(connector)),
130 );
131
132 presentation.save_to_file(&path)?;
133 println!("Wrote {}", path.display());
134 Ok(())
135}Sourcepub fn with_flip_horizontal(self, flip: bool) -> ShapeGroup
pub fn with_flip_horizontal(self, flip: bool) -> ShapeGroup
Mirrors the whole group horizontally.
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("pptx_grouping_and_connectors.pptx");
18
19 // Every shape below sets an explicit fill (and the connector an
20 // explicit line): with neither a fill/line nor a `<p:style>` theme
21 // reference, a shape has nothing to paint and renders as fully
22 // invisible — the slide then looks blank even though the shapes are
23 // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24 // explicit `Fill`/`Line` is the only way to make a shape actually show.
25 let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27 let circle = AutoShape::new(11, "Circle").with_properties(
28 ShapeProperties::new()
29 .with_transform(
30 Transform2D::new()
31 .with_offset(0, 0)
32 .with_extent(1_000_000, 1_000_000),
33 )
34 .with_fill(circle_fill()),
35 );
36 let label = AutoShape::new(12, "Label")
37 .with_properties(
38 ShapeProperties::new()
39 .with_transform(
40 Transform2D::new()
41 .with_offset(1_200_000, 300_000)
42 .with_extent(1_500_000, 400_000),
43 )
44 .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45 )
46 .with_text_body(
47 TextBody::new()
48 .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49 );
50
51 let group = ShapeGroup::new(2, "Group")
52 .with_transform(
53 (838_200, 838_200),
54 (2_700_000, 1_000_000),
55 (0, 0),
56 (2_700_000, 1_000_000),
57 )
58 .with_shape(Shape::AutoShape(circle))
59 .with_shape(Shape::AutoShape(label));
60
61 let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62 ShapeProperties::new()
63 .with_transform(
64 Transform2D::new()
65 .with_offset(0, 0)
66 .with_extent(1_000_000, 1_000_000),
67 )
68 .with_fill(circle_fill()),
69 );
70 let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71 .with_transform(
72 (838_200, 838_200),
73 (1_000_000, 1_000_000),
74 (0, 0),
75 (1_000_000, 1_000_000),
76 )
77 .with_rotation_degrees(45.0)
78 .with_flip_horizontal(true)
79 .with_shape(Shape::AutoShape(rotated_circle));
80
81 let box_a = AutoShape::new(2, "Box A").with_properties(
82 ShapeProperties::new()
83 .with_transform(
84 Transform2D::new()
85 .with_offset(838_200, 838_200)
86 .with_extent(1_000_000, 1_000_000),
87 )
88 .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89 );
90 let box_b = AutoShape::new(3, "Box B").with_properties(
91 ShapeProperties::new()
92 .with_transform(
93 Transform2D::new()
94 .with_offset(3_500_000, 838_200)
95 .with_extent(1_000_000, 1_000_000),
96 )
97 .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98 );
99 // `Connector::new` leaves position/size unset, which the writer then
100 // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101 // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102 // alone don't supply geometry; PowerPoint only recomputes it once you
103 // drag one of the attached shapes. So this also sets an explicit
104 // transform spanning Box A's right edge to Box B's left edge.
105 let connector = Connector::new(4, "Connector")
106 .with_properties(
107 ShapeProperties::new()
108 .with_transform(
109 Transform2D::new()
110 .with_offset(1_838_200, 1_338_200)
111 .with_extent(1_662_000, 0),
112 )
113 .with_line(
114 Line::new()
115 .with_width_emu(25_400)
116 .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117 ),
118 )
119 .with_start_connection(2, 0)
120 .with_end_connection(3, 0);
121
122 let presentation = Presentation::new()
123 .with_slide(Slide::new().with_shape(Shape::Group(group)))
124 .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125 .with_slide(
126 Slide::new()
127 .with_shape(Shape::AutoShape(box_a))
128 .with_shape(Shape::AutoShape(box_b))
129 .with_shape(Shape::Connector(connector)),
130 );
131
132 presentation.save_to_file(&path)?;
133 println!("Wrote {}", path.display());
134 Ok(())
135}Sourcepub fn with_flip_vertical(self, flip: bool) -> ShapeGroup
pub fn with_flip_vertical(self, flip: bool) -> ShapeGroup
Mirrors the whole group vertically.
Sourcepub fn with_shape(self, shape: Shape) -> ShapeGroup
pub fn with_shape(self, shape: Shape) -> ShapeGroup
Appends a child shape.
Examples found in repository?
16fn main() -> office_toolkit::Result<()> {
17 let path = output_path("pptx_grouping_and_connectors.pptx");
18
19 // Every shape below sets an explicit fill (and the connector an
20 // explicit line): with neither a fill/line nor a `<p:style>` theme
21 // reference, a shape has nothing to paint and renders as fully
22 // invisible — the slide then looks blank even though the shapes are
23 // there. `AutoShape`/`Connector` have no `<p:style>` support yet, so an
24 // explicit `Fill`/`Line` is the only way to make a shape actually show.
25 let circle_fill = || Fill::Solid(Color::Rgb("4472C4".to_string()));
26
27 let circle = AutoShape::new(11, "Circle").with_properties(
28 ShapeProperties::new()
29 .with_transform(
30 Transform2D::new()
31 .with_offset(0, 0)
32 .with_extent(1_000_000, 1_000_000),
33 )
34 .with_fill(circle_fill()),
35 );
36 let label = AutoShape::new(12, "Label")
37 .with_properties(
38 ShapeProperties::new()
39 .with_transform(
40 Transform2D::new()
41 .with_offset(1_200_000, 300_000)
42 .with_extent(1_500_000, 400_000),
43 )
44 .with_fill(Fill::Solid(Color::Rgb("E8622C".to_string()))),
45 )
46 .with_text_body(
47 TextBody::new()
48 .with_paragraph(TextParagraph::new().with_run(TextRun::text("Grouped label"))),
49 );
50
51 let group = ShapeGroup::new(2, "Group")
52 .with_transform(
53 (838_200, 838_200),
54 (2_700_000, 1_000_000),
55 (0, 0),
56 (2_700_000, 1_000_000),
57 )
58 .with_shape(Shape::AutoShape(circle))
59 .with_shape(Shape::AutoShape(label));
60
61 let rotated_circle = AutoShape::new(11, "Circle").with_properties(
62 ShapeProperties::new()
63 .with_transform(
64 Transform2D::new()
65 .with_offset(0, 0)
66 .with_extent(1_000_000, 1_000_000),
67 )
68 .with_fill(circle_fill()),
69 );
70 let rotated_group = ShapeGroup::new(2, "Rotated and flipped group")
71 .with_transform(
72 (838_200, 838_200),
73 (1_000_000, 1_000_000),
74 (0, 0),
75 (1_000_000, 1_000_000),
76 )
77 .with_rotation_degrees(45.0)
78 .with_flip_horizontal(true)
79 .with_shape(Shape::AutoShape(rotated_circle));
80
81 let box_a = AutoShape::new(2, "Box A").with_properties(
82 ShapeProperties::new()
83 .with_transform(
84 Transform2D::new()
85 .with_offset(838_200, 838_200)
86 .with_extent(1_000_000, 1_000_000),
87 )
88 .with_fill(Fill::Solid(Color::Rgb("2E86AB".to_string()))),
89 );
90 let box_b = AutoShape::new(3, "Box B").with_properties(
91 ShapeProperties::new()
92 .with_transform(
93 Transform2D::new()
94 .with_offset(3_500_000, 838_200)
95 .with_extent(1_000_000, 1_000_000),
96 )
97 .with_fill(Fill::Solid(Color::Rgb("6FB98F".to_string()))),
98 );
99 // `Connector::new` leaves position/size unset, which the writer then
100 // emits as a zero-size `<a:xfrm>` (off 0,0 / ext 0,0) — a real point
101 // with no length, invisible regardless of line/fill. `stCxn`/`endCxn`
102 // alone don't supply geometry; PowerPoint only recomputes it once you
103 // drag one of the attached shapes. So this also sets an explicit
104 // transform spanning Box A's right edge to Box B's left edge.
105 let connector = Connector::new(4, "Connector")
106 .with_properties(
107 ShapeProperties::new()
108 .with_transform(
109 Transform2D::new()
110 .with_offset(1_838_200, 1_338_200)
111 .with_extent(1_662_000, 0),
112 )
113 .with_line(
114 Line::new()
115 .with_width_emu(25_400)
116 .with_fill(Fill::Solid(Color::Rgb("000000".to_string()))),
117 ),
118 )
119 .with_start_connection(2, 0)
120 .with_end_connection(3, 0);
121
122 let presentation = Presentation::new()
123 .with_slide(Slide::new().with_shape(Shape::Group(group)))
124 .with_slide(Slide::new().with_shape(Shape::Group(rotated_group)))
125 .with_slide(
126 Slide::new()
127 .with_shape(Shape::AutoShape(box_a))
128 .with_shape(Shape::AutoShape(box_b))
129 .with_shape(Shape::Connector(connector)),
130 );
131
132 presentation.save_to_file(&path)?;
133 println!("Wrote {}", path.display());
134 Ok(())
135}Trait Implementations§
Source§impl Clone for ShapeGroup
impl Clone for ShapeGroup
Source§fn clone(&self) -> ShapeGroup
fn clone(&self) -> ShapeGroup
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more