Skip to main content

ShapeGroup

Struct ShapeGroup 

Source
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

Source

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?
examples/pptx_grouping_and_connectors.rs (line 51)
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}
Source

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?
examples/pptx_grouping_and_connectors.rs (lines 52-57)
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}
Source

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?
examples/pptx_grouping_and_connectors.rs (line 77)
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}
Source

pub fn with_flip_horizontal(self, flip: bool) -> ShapeGroup

Mirrors the whole group horizontally.

Examples found in repository?
examples/pptx_grouping_and_connectors.rs (line 78)
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}
Source

pub fn with_flip_vertical(self, flip: bool) -> ShapeGroup

Mirrors the whole group vertically.

Source

pub fn with_shape(self, shape: Shape) -> ShapeGroup

Appends a child shape.

Examples found in repository?
examples/pptx_grouping_and_connectors.rs (line 58)
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

Source§

fn clone(&self) -> ShapeGroup

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ShapeGroup

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl PartialEq for ShapeGroup

Source§

fn eq(&self, other: &ShapeGroup) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ShapeGroup

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.