1pub mod action;
2pub mod autoshape;
3pub mod connector;
4pub mod freeform;
5pub mod graphfrm;
6pub mod group;
7pub mod ole;
8pub mod parser;
9pub mod picture;
10pub mod placeholder;
11mod shape_accessors;
12pub mod shapetree;
13
14pub use action::{ActionSetting, Hyperlink};
15pub use autoshape::AutoShape;
16pub use connector::Connector;
17pub use freeform::FreeformBuilder;
18pub use graphfrm::GraphicFrame;
19pub use group::GroupShape;
20pub use ole::OleObject;
21pub use picture::Picture;
22pub use placeholder::PlaceholderFormat;
23pub use shapetree::ShapeTree;
24
25use std::fmt;
26
27use crate::units::{Emu, ShapeId};
28use crate::xml_util::WriteXml;
29
30pub trait ShapeProperties {
32 fn shape_id(&self) -> ShapeId;
34 fn name(&self) -> &str;
36 fn left(&self) -> Emu;
38 fn top(&self) -> Emu;
40 fn width(&self) -> Emu;
42 fn height(&self) -> Emu;
44 fn rotation(&self) -> f64;
46}
47
48macro_rules! impl_shape_properties {
50 ($ty:ty) => {
51 impl ShapeProperties for $ty {
52 #[inline]
53 fn shape_id(&self) -> ShapeId {
54 self.shape_id
55 }
56 #[inline]
57 fn name(&self) -> &str {
58 &self.name
59 }
60 #[inline]
61 fn left(&self) -> Emu {
62 self.left
63 }
64 #[inline]
65 fn top(&self) -> Emu {
66 self.top
67 }
68 #[inline]
69 fn width(&self) -> Emu {
70 self.width
71 }
72 #[inline]
73 fn height(&self) -> Emu {
74 self.height
75 }
76 #[inline]
77 fn rotation(&self) -> f64 {
78 self.rotation
79 }
80 }
81 };
82}
83
84impl_shape_properties!(AutoShape);
85impl_shape_properties!(Picture);
86impl_shape_properties!(GraphicFrame);
87impl_shape_properties!(GroupShape);
88impl_shape_properties!(Connector);
89impl_shape_properties!(OleObject);
90
91#[non_exhaustive]
95#[derive(Debug, Clone, PartialEq)]
96pub enum Shape {
97 AutoShape(Box<AutoShape>),
98 Picture(Box<Picture>),
99 GraphicFrame(Box<GraphicFrame>),
100 GroupShape(Box<GroupShape>),
101 Connector(Connector),
102 OleObject(OleObject),
103}
104
105macro_rules! dispatch_shape {
107 ($self:expr, $method:ident) => {
108 match $self {
109 Shape::AutoShape(s) => s.$method(),
110 Shape::Picture(s) => s.$method(),
111 Shape::GraphicFrame(s) => s.$method(),
112 Shape::GroupShape(s) => s.$method(),
113 Shape::Connector(s) => s.$method(),
114 Shape::OleObject(s) => s.$method(),
115 }
116 };
117}
118
119impl Shape {
120 #[inline]
122 #[must_use]
123 pub fn shape_id(&self) -> ShapeId {
124 dispatch_shape!(self, shape_id)
125 }
126 #[inline]
128 #[must_use]
129 pub fn name(&self) -> &str {
130 dispatch_shape!(self, name)
131 }
132 #[inline]
134 pub fn left(&self) -> Emu {
135 dispatch_shape!(self, left)
136 }
137 #[inline]
139 pub fn top(&self) -> Emu {
140 dispatch_shape!(self, top)
141 }
142 #[inline]
144 pub fn width(&self) -> Emu {
145 dispatch_shape!(self, width)
146 }
147 #[inline]
149 pub fn height(&self) -> Emu {
150 dispatch_shape!(self, height)
151 }
152 #[inline]
154 #[must_use]
155 pub fn rotation(&self) -> f64 {
156 dispatch_shape!(self, rotation)
157 }
158
159 #[inline]
161 #[must_use]
162 pub const fn has_text_frame(&self) -> bool {
163 match self {
164 Self::AutoShape(a) => a.has_text_frame(),
165 _ => false,
166 }
167 }
168
169 #[inline]
171 #[must_use]
172 pub fn has_table(&self) -> bool {
173 matches!(self, Self::GraphicFrame(g) if g.has_table)
174 }
175
176 #[inline]
178 #[must_use]
179 pub const fn is_placeholder(&self) -> bool {
180 match self {
181 Self::AutoShape(s) => s.placeholder.is_some(),
182 Self::Picture(s) => s.placeholder.is_some(),
183 Self::GraphicFrame(s) => s.placeholder.is_some(),
184 Self::GroupShape(_) | Self::Connector(_) | Self::OleObject(_) => false,
185 }
186 }
187
188 #[inline]
190 #[must_use]
191 pub const fn placeholder(&self) -> Option<&PlaceholderFormat> {
192 match self {
193 Self::AutoShape(s) => s.placeholder.as_ref(),
194 Self::Picture(s) => s.placeholder.as_ref(),
195 Self::GraphicFrame(s) => s.placeholder.as_ref(),
196 Self::GroupShape(_) | Self::Connector(_) | Self::OleObject(_) => None,
197 }
198 }
199}
200
201impl WriteXml for Shape {
202 fn write_xml<W: std::fmt::Write>(&self, w: &mut W) -> std::fmt::Result {
203 match self {
204 Self::AutoShape(s) => s.write_xml(w),
205 Self::Picture(s) => s.write_xml(w),
206 Self::GroupShape(s) => s.write_xml(w),
207 Self::Connector(s) => s.write_xml(w),
208 Self::OleObject(s) => s.write_xml(w),
209 Self::GraphicFrame(_) => {
210 Ok(())
214 }
215 }
216 }
217}
218
219impl fmt::Display for Shape {
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 let kind = match self {
222 Self::AutoShape(_) => "AutoShape",
223 Self::Picture(_) => "Picture",
224 Self::GraphicFrame(_) => "GraphicFrame",
225 Self::GroupShape(_) => "GroupShape",
226 Self::Connector(_) => "Connector",
227 Self::OleObject(_) => "OleObject",
228 };
229 write!(f, "{}(\"{}\")", kind, self.name())
230 }
231}