umya_spreadsheet/structs/drawing/
outline.rs1use std::io::Cursor;
3
4use quick_xml::{
5 Reader,
6 Writer,
7 events::{
8 BytesStart,
9 Event,
10 },
11};
12
13use super::{
14 Bevel,
15 GradientFill,
16 Miter,
17 NoFill,
18 PenAlignmentValues,
19 PresetDash,
20 Round,
21 SolidFill,
22 TailEnd,
23};
24use crate::{
25 StringValue,
26 drawing::SystemColor,
27 reader::driver::{
28 get_attribute,
29 set_string_from_xml,
30 xml_read_loop,
31 },
32 structs::{
33 EnumValue,
34 UInt32Value,
35 },
36 writer::driver::{
37 write_end_tag,
38 write_start_tag,
39 },
40};
41
42#[derive(Clone, Default, Debug)]
43pub struct Outline {
44 width: UInt32Value,
45 cap_type: StringValue,
46 compound_line_type: StringValue,
47 solid_fill: Option<Box<SolidFill>>,
48 gradient_fill: Option<Box<GradientFill>>,
49 tail_end: Option<Box<TailEnd>>,
50 no_fill: Option<NoFill>,
51 bevel: Option<Box<Bevel>>,
52 preset_dash: Option<PresetDash>,
53 miter: Option<Miter>,
54 round: Option<Round>,
55 alignment: EnumValue<PenAlignmentValues>,
56 system_color: Option<Box<SystemColor>>,
57}
58
59impl Outline {
60 #[inline]
61 #[must_use]
62 pub fn width(&self) -> u32 {
63 self.width.value()
64 }
65
66 #[inline]
67 #[must_use]
68 #[deprecated(since = "3.0.0", note = "Use width()")]
69 pub fn get_width(&self) -> u32 {
70 self.width()
71 }
72
73 #[inline]
74 pub fn set_width(&mut self, value: u32) -> &mut Self {
75 self.width.set_value(value);
76 self
77 }
78
79 #[inline]
80 #[must_use]
81 pub fn cap_type(&self) -> Option<&str> {
82 self.cap_type.value()
83 }
84
85 #[inline]
86 #[must_use]
87 #[deprecated(since = "3.0.0", note = "Use cap_type()")]
88 pub fn get_cap_type(&self) -> Option<&str> {
89 self.cap_type()
90 }
91
92 #[inline]
93 pub fn set_cap_type<S: Into<String>>(&mut self, value: S) -> &mut Self {
94 self.cap_type.set_value(value);
95 self
96 }
97
98 #[inline]
99 #[must_use]
100 pub fn compound_line_type(&self) -> Option<&str> {
101 self.compound_line_type.value()
102 }
103
104 #[inline]
105 #[must_use]
106 #[deprecated(since = "3.0.0", note = "Use compound_line_type()")]
107 pub fn get_compound_line_type(&self) -> Option<&str> {
108 self.compound_line_type()
109 }
110
111 #[inline]
112 pub fn set_compound_line_type<S: Into<String>>(&mut self, value: S) -> &mut Self {
113 self.compound_line_type.set_value(value);
114 self
115 }
116
117 #[inline]
118 #[must_use]
119 pub fn solid_fill(&self) -> Option<&SolidFill> {
120 self.solid_fill.as_deref()
121 }
122
123 #[inline]
124 #[must_use]
125 #[deprecated(since = "3.0.0", note = "Use solid_fill()")]
126 pub fn get_solid_fill(&self) -> Option<&SolidFill> {
127 self.solid_fill()
128 }
129
130 #[inline]
131 pub fn solid_fill_mut(&mut self) -> Option<&mut SolidFill> {
132 self.solid_fill.as_deref_mut()
133 }
134
135 #[inline]
136 #[deprecated(since = "3.0.0", note = "Use solid_fill_mut()")]
137 pub fn get_solid_fill_mut(&mut self) -> Option<&mut SolidFill> {
138 self.solid_fill_mut()
139 }
140
141 #[inline]
142 pub fn set_solid_fill(&mut self, value: SolidFill) -> &mut Self {
143 self.solid_fill = Some(Box::new(value));
144 self
145 }
146
147 #[inline]
148 #[must_use]
149 pub fn gradient_fill(&self) -> Option<&GradientFill> {
150 self.gradient_fill.as_deref()
151 }
152
153 #[inline]
154 #[must_use]
155 #[deprecated(since = "3.0.0", note = "Use gradient_fill()")]
156 pub fn get_gradient_fill(&self) -> Option<&GradientFill> {
157 self.gradient_fill()
158 }
159
160 #[inline]
161 pub fn gradient_fill_mut(&mut self) -> Option<&mut GradientFill> {
162 self.gradient_fill.as_deref_mut()
163 }
164
165 #[inline]
166 #[deprecated(since = "3.0.0", note = "Use gradient_fill_mut()")]
167 pub fn get_gradient_fill_mut(&mut self) -> Option<&mut GradientFill> {
168 self.gradient_fill_mut()
169 }
170
171 #[inline]
172 pub fn set_gradient_fill(&mut self, value: GradientFill) -> &mut Self {
173 self.gradient_fill = Some(Box::new(value));
174 self
175 }
176
177 #[inline]
178 #[must_use]
179 pub fn tail_end(&self) -> Option<&TailEnd> {
180 self.tail_end.as_deref()
181 }
182
183 #[inline]
184 #[must_use]
185 #[deprecated(since = "3.0.0", note = "Use tail_end()")]
186 pub fn get_tail_end(&self) -> Option<&TailEnd> {
187 self.tail_end()
188 }
189
190 #[inline]
191 pub fn tail_end_mut(&mut self) -> Option<&mut TailEnd> {
192 self.tail_end.as_deref_mut()
193 }
194
195 #[inline]
196 #[deprecated(since = "3.0.0", note = "Use tail_end_mut()")]
197 pub fn get_tail_end_mut(&mut self) -> Option<&mut TailEnd> {
198 self.tail_end_mut()
199 }
200
201 #[inline]
202 pub fn set_tail_end(&mut self, value: TailEnd) -> &mut Self {
203 self.tail_end = Some(Box::new(value));
204 self
205 }
206
207 #[inline]
208 #[must_use]
209 pub fn no_fill(&self) -> Option<&NoFill> {
210 self.no_fill.as_ref()
211 }
212
213 #[inline]
214 #[must_use]
215 #[deprecated(since = "3.0.0", note = "Use no_fill()")]
216 pub fn get_no_fill(&self) -> Option<&NoFill> {
217 self.no_fill()
218 }
219
220 #[inline]
221 pub fn no_fill_mut(&mut self) -> Option<&mut NoFill> {
222 self.no_fill.as_mut()
223 }
224
225 #[inline]
226 #[deprecated(since = "3.0.0", note = "Use no_fill_mut()")]
227 pub fn get_no_fill_mut(&mut self) -> Option<&mut NoFill> {
228 self.no_fill_mut()
229 }
230
231 #[inline]
232 pub fn set_no_fill(&mut self, value: NoFill) -> &mut Self {
233 self.no_fill = Some(value);
234 self
235 }
236
237 #[inline]
238 #[must_use]
239 pub fn bevel(&self) -> Option<&Bevel> {
240 self.bevel.as_deref()
241 }
242
243 #[inline]
244 #[must_use]
245 #[deprecated(since = "3.0.0", note = "Use bevel()")]
246 pub fn get_bevel(&self) -> Option<&Bevel> {
247 self.bevel()
248 }
249
250 #[inline]
251 pub fn bevel_mut(&mut self) -> Option<&mut Bevel> {
252 self.bevel.as_deref_mut()
253 }
254
255 #[inline]
256 #[deprecated(since = "3.0.0", note = "Use bevel_mut()")]
257 pub fn get_bevel_mut(&mut self) -> Option<&mut Bevel> {
258 self.bevel_mut()
259 }
260
261 #[inline]
262 pub fn set_bevel(&mut self, value: Bevel) -> &mut Self {
263 self.bevel = Some(Box::new(value));
264 self
265 }
266
267 #[inline]
268 #[must_use]
269 pub fn preset_dash(&self) -> Option<&PresetDash> {
270 self.preset_dash.as_ref()
271 }
272
273 #[inline]
274 #[must_use]
275 #[deprecated(since = "3.0.0", note = "Use preset_dash()")]
276 pub fn get_preset_dash(&self) -> Option<&PresetDash> {
277 self.preset_dash()
278 }
279
280 #[inline]
281 pub fn preset_dash_mut(&mut self) -> Option<&mut PresetDash> {
282 self.preset_dash.as_mut()
283 }
284
285 #[inline]
286 #[deprecated(since = "3.0.0", note = "Use preset_dash_mut()")]
287 pub fn get_preset_dash_mut(&mut self) -> Option<&mut PresetDash> {
288 self.preset_dash_mut()
289 }
290
291 #[inline]
292 pub fn set_preset_dash(&mut self, value: PresetDash) -> &mut Self {
293 self.preset_dash = Some(value);
294 self
295 }
296
297 #[inline]
298 #[must_use]
299 pub fn miter(&self) -> Option<&Miter> {
300 self.miter.as_ref()
301 }
302
303 #[inline]
304 #[must_use]
305 #[deprecated(since = "3.0.0", note = "Use miter()")]
306 pub fn get_miter(&self) -> Option<&Miter> {
307 self.miter()
308 }
309
310 #[inline]
311 pub fn miter_mut(&mut self) -> Option<&mut Miter> {
312 self.miter.as_mut()
313 }
314
315 #[inline]
316 #[deprecated(since = "3.0.0", note = "Use miter_mut()")]
317 pub fn get_miter_mut(&mut self) -> Option<&mut Miter> {
318 self.miter_mut()
319 }
320
321 #[inline]
322 pub fn set_miter(&mut self, value: Miter) -> &mut Self {
323 self.miter = Some(value);
324 self
325 }
326
327 #[inline]
328 #[must_use]
329 pub fn round(&self) -> Option<&Round> {
330 self.round.as_ref()
331 }
332
333 #[inline]
334 #[must_use]
335 #[deprecated(since = "3.0.0", note = "Use round()")]
336 pub fn get_round(&self) -> Option<&Round> {
337 self.round()
338 }
339
340 #[inline]
341 pub fn round_mut(&mut self) -> Option<&mut Round> {
342 self.round.as_mut()
343 }
344
345 #[inline]
346 #[deprecated(since = "3.0.0", note = "Use round_mut()")]
347 pub fn get_round_mut(&mut self) -> Option<&mut Round> {
348 self.round_mut()
349 }
350
351 #[inline]
352 pub fn set_round(&mut self, value: Round) -> &mut Self {
353 self.round = Some(value);
354 self
355 }
356
357 #[inline]
358 #[must_use]
359 pub fn alignment(&self) -> &PenAlignmentValues {
360 self.alignment.value()
361 }
362
363 #[inline]
364 #[must_use]
365 #[deprecated(since = "3.0.0", note = "Use alignment()")]
366 pub fn get_alignment(&self) -> &PenAlignmentValues {
367 self.alignment()
368 }
369
370 #[inline]
371 pub fn set_alignment(&mut self, value: PenAlignmentValues) {
372 self.alignment.set_value(value);
373 }
374
375 #[inline]
376 #[must_use]
377 pub fn system_color(&self) -> Option<&SystemColor> {
378 self.system_color.as_deref()
379 }
380
381 #[inline]
382 #[must_use]
383 #[deprecated(since = "3.0.0", note = "Use system_color()")]
384 pub fn get_system_color(&self) -> Option<&SystemColor> {
385 self.system_color()
386 }
387
388 #[inline]
389 pub fn system_color_mut(&mut self) -> Option<&mut SystemColor> {
390 self.system_color.as_deref_mut()
391 }
392
393 #[inline]
394 #[deprecated(since = "3.0.0", note = "Use system_color_mut()")]
395 pub fn get_system_color_mut(&mut self) -> Option<&mut SystemColor> {
396 self.system_color_mut()
397 }
398
399 #[inline]
400 pub fn set_system_color(&mut self, value: SystemColor) {
401 self.system_color = Some(Box::new(value));
402 }
403
404 pub(crate) fn set_attributes<R: std::io::BufRead>(
405 &mut self,
406 reader: &mut Reader<R>,
407 e: &BytesStart,
408 ) {
409 if let Some(v) = get_attribute(e, b"w") {
410 self.set_width(v.parse::<u32>().unwrap());
411 }
412
413 if let Some(v) = get_attribute(e, b"cap") {
414 self.set_cap_type(v);
415 }
416
417 if let Some(v) = get_attribute(e, b"cmpd") {
418 self.set_compound_line_type(v);
419 }
420
421 set_string_from_xml!(self, e, alignment, "algn");
422
423 xml_read_loop!(
424 reader,
425 ref n @ (Event::Empty(ref e) | Event::Start(ref e)) => {
426 let is_empty = matches!(n, Event::Empty(_));
427 match e.name().into_inner() {
428 b"a:solidFill" => {
429 let mut solid_fill = SolidFill::default();
430 solid_fill.set_attributes(reader, e);
431 self.set_solid_fill(solid_fill);
432 }
433 b"a:gradFill" => {
434 let mut obj = GradientFill::default();
435 obj.set_attributes(reader, e);
436 self.set_gradient_fill(obj);
437 }
438 b"a:tailEnd" => {
439 let mut obj = TailEnd::default();
440 obj.set_attributes(reader, e, is_empty);
441 self.set_tail_end(obj);
442 }
443 b"a:noFill" => {
444 let obj = NoFill::default();
445 NoFill::set_attributes(reader, e, is_empty);
446 self.set_no_fill(obj);
447 }
448 b"a:bevel" => {
449 let obj = Bevel::default();
450 Bevel::set_attributes(reader, e, is_empty);
451 self.set_bevel(obj);
452 }
453 b"a:miter" => {
454 let mut obj = Miter::default();
455 obj.set_attributes(reader, e, is_empty);
456 self.set_miter(obj);
457 }
458 b"a:prstDash" => {
459 let mut obj = PresetDash::default();
460 obj.set_attributes(reader, e, is_empty);
461 self.set_preset_dash(obj);
462 }
463 b"a:round" => {
464 let obj = Round::default();
465 Round::set_attributes(reader, e, is_empty);
466 self.set_round(obj);
467 }
468 b"a:sysClr" => {
469 let mut obj = SystemColor::default();
470 obj.set_attributes(reader, e, is_empty);
471 self.set_system_color(obj);
472 }
473 _ => (),
474 }
475 },
476 Event::End(ref e) => {
477 if e.name().into_inner() == b"a:ln" {
478 return;
479 }
480 },
481 Event::Eof => panic!("Error: Could not find {} end element", "a:ln")
482 );
483 }
484
485 pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
486 let mut attributes: crate::structs::AttrCollection = Vec::new();
488 let width = self.width.value_string();
489 if self.width.has_value() {
490 attributes.push(("w", &width).into());
491 }
492 if let Some(v) = self.cap_type.value() {
493 attributes.push(("cap", v).into());
494 }
495 if let Some(v) = self.compound_line_type.value() {
496 attributes.push(("cmpd", v).into());
497 }
498 if self.alignment.has_value() {
499 attributes.push(("algn", (self.alignment.value_string())).into());
500 }
501 write_start_tag(writer, "a:ln", attributes, false);
502
503 if let Some(v) = &self.solid_fill {
505 v.write_to(writer);
506 }
507
508 if let Some(v) = &self.gradient_fill {
510 v.write_to(writer);
511 }
512
513 if self.round.is_some() {
515 Round::write_to(writer);
516 }
517
518 if let Some(v) = &self.tail_end {
520 v.write_to(writer);
521 }
522
523 if self.no_fill.is_some() {
525 NoFill::write_to(writer);
526 }
527
528 if self.bevel.is_some() {
530 Bevel::write_to(writer);
531 }
532
533 if let Some(v) = &self.preset_dash {
535 v.write_to(writer);
536 }
537
538 if let Some(v) = &self.miter {
540 v.write_to(writer);
541 }
542
543 write_end_tag(writer, "a:ln");
544 }
545}