pptx_rs/shape/
connector.rs1use crate::oxml::shape::Connector as OxmlCxn;
25use crate::oxml::simpletypes::MsoConnectorType;
26use crate::oxml::simpletypes::PresetGeometry;
27use crate::oxml::sppr::Geometry;
28use crate::shape::base::Shape;
29use crate::units::{Emu, EmuPoint};
30
31#[derive(Clone, Debug, Default)]
33pub struct Connector {
34 pub(crate) cxn: OxmlCxn,
36}
37
38impl Connector {
39 pub fn from_cxn(c: OxmlCxn) -> Self {
41 Connector { cxn: c }
42 }
43
44 pub fn new(name: impl Into<String>) -> Self {
46 Connector {
47 cxn: OxmlCxn {
48 name: name.into(),
49 ..Default::default()
50 },
51 }
52 }
53
54 pub fn new_with_type(name: impl Into<String>, connector_type: MsoConnectorType) -> Self {
71 let mut cxn = OxmlCxn {
72 name: name.into(),
73 ..Default::default()
74 };
75 cxn.connector_type = Some(connector_type);
76 cxn.properties.geometry =
78 Some(Geometry::preset(connector_type_to_geometry(connector_type)));
79 Connector { cxn }
80 }
81
82 pub fn recompute_xfrm(&mut self) {
95 match (self.cxn.begin, self.cxn.end) {
96 (Some((bx, by)), Some((ex, ey))) => {
97 let min_x = bx.value().min(ex.value());
98 let min_y = by.value().min(ey.value());
99 let max_x = bx.value().max(ex.value());
100 let max_y = by.value().max(ey.value());
101 self.cxn.properties.xfrm.off_x = Some(Emu(min_x));
102 self.cxn.properties.xfrm.off_y = Some(Emu(min_y));
103 self.cxn.properties.xfrm.ext_cx = Some(Emu(max_x - min_x));
104 self.cxn.properties.xfrm.ext_cy = Some(Emu(max_y - min_y));
105 }
106 _ => {
107 self.cxn.properties.xfrm.off_x = Some(Emu(0));
108 self.cxn.properties.xfrm.off_y = Some(Emu(0));
109 self.cxn.properties.xfrm.ext_cx = Some(Emu(0));
110 self.cxn.properties.xfrm.ext_cy = Some(Emu(0));
111 }
112 }
113 }
114
115 pub fn cxn(&self) -> &OxmlCxn {
117 &self.cxn
118 }
119 pub fn cxn_mut(&mut self) -> &mut OxmlCxn {
121 &mut self.cxn
122 }
123
124 pub fn properties(&self) -> &crate::oxml::sppr::ShapeProperties {
126 &self.cxn.properties
127 }
128 pub fn properties_mut(&mut self) -> &mut crate::oxml::sppr::ShapeProperties {
130 &mut self.cxn.properties
131 }
132
133 pub fn begin(&self) -> Option<EmuPoint> {
135 self.cxn.begin.map(|(x, y)| EmuPoint(x.value(), y.value()))
136 }
137 pub fn set_begin(&mut self, p: EmuPoint) {
143 self.cxn.begin = Some((Emu(p.0), Emu(p.1)));
144 self.recompute_xfrm();
145 }
146
147 pub fn end(&self) -> Option<EmuPoint> {
149 self.cxn.end.map(|(x, y)| EmuPoint(x.value(), y.value()))
150 }
151 pub fn set_end(&mut self, p: EmuPoint) {
153 self.cxn.end = Some((Emu(p.0), Emu(p.1)));
154 self.recompute_xfrm();
155 }
156
157 pub fn connector_type(&self) -> Option<MsoConnectorType> {
159 self.cxn.connector_type
160 }
161 pub fn set_connector_type(&mut self, t: MsoConnectorType) {
163 self.cxn.connector_type = Some(t);
164 self.cxn.properties.geometry = Some(Geometry::preset(connector_type_to_geometry(t)));
165 }
166
167 pub fn begin_connection(&self) -> Option<(u32, u32)> {
169 self.cxn.st_cxn
170 }
171 pub fn set_begin_connection(&mut self, shape_id: u32, idx: u32) {
173 self.cxn.st_cxn = Some((shape_id, idx));
174 }
175
176 pub fn end_connection(&self) -> Option<(u32, u32)> {
178 self.cxn.end_cxn
179 }
180 pub fn set_end_connection(&mut self, shape_id: u32, idx: u32) {
182 self.cxn.end_cxn = Some((shape_id, idx));
183 }
184}
185
186fn connector_type_to_geometry(t: MsoConnectorType) -> PresetGeometry {
190 match t {
191 MsoConnectorType::Straight => PresetGeometry::Line,
192 MsoConnectorType::Elbow => PresetGeometry::BentConnector2,
193 MsoConnectorType::Curve => PresetGeometry::CurvedConnector2,
194 MsoConnectorType::BentConnector3 => PresetGeometry::BentConnector3,
195 MsoConnectorType::BentConnector4 => PresetGeometry::BentConnector4,
196 MsoConnectorType::BentConnector5 => PresetGeometry::BentConnector5,
197 MsoConnectorType::CurvedConnector3 => PresetGeometry::CurvedConnector3,
198 MsoConnectorType::CurvedConnector4 => PresetGeometry::CurvedConnector4,
199 MsoConnectorType::CurvedConnector5 => PresetGeometry::CurvedConnector5,
200 }
201}
202
203impl Shape for Connector {
204 fn id(&self) -> u32 {
205 self.cxn.id
206 }
207 fn set_id(&mut self, id: u32) {
208 self.cxn.id = id;
209 }
210 fn name(&self) -> &str {
211 &self.cxn.name
212 }
213 fn set_name(&mut self, name: String) {
214 self.cxn.name = name;
215 }
216 fn shape_type(&self) -> &'static str {
217 "connector"
218 }
219
220 fn left(&self) -> Emu {
221 self.cxn.properties.xfrm.off_x.unwrap_or_default()
222 }
223 fn set_left(&mut self, emu: Emu) {
224 self.cxn.properties.xfrm.off_x = Some(emu);
225 }
226 fn top(&self) -> Emu {
227 self.cxn.properties.xfrm.off_y.unwrap_or_default()
228 }
229 fn set_top(&mut self, emu: Emu) {
230 self.cxn.properties.xfrm.off_y = Some(emu);
231 }
232 fn width(&self) -> Emu {
233 self.cxn.properties.xfrm.ext_cx.unwrap_or_default()
234 }
235 fn set_width(&mut self, emu: Emu) {
236 self.cxn.properties.xfrm.ext_cx = Some(emu);
237 }
238 fn height(&self) -> Emu {
239 self.cxn.properties.xfrm.ext_cy.unwrap_or_default()
240 }
241 fn set_height(&mut self, emu: Emu) {
242 self.cxn.properties.xfrm.ext_cy = Some(emu);
243 }
244
245 fn rotation(&self) -> f64 {
246 self.cxn.properties.rot_deg.unwrap_or(0.0)
247 }
248 fn set_rotation(&mut self, deg: f64) {
249 self.cxn.properties.rot_deg = Some(deg);
250 let rot = (deg * 60_000.0) as i32;
251 self.cxn.properties.xfrm.rot = Some(rot);
252 }
253}