Skip to main content

umya_spreadsheet/structs/drawing/
run_properties.rs

1use std::io::Cursor;
2
3use quick_xml::{
4    Reader,
5    Writer,
6    events::{
7        BytesStart,
8        Event,
9    },
10};
11
12use super::{
13    super::{
14        EnumValue,
15        Int32Value,
16    },
17    EffectList,
18    GradientFill,
19    NoFill,
20    Outline,
21    SolidFill,
22    TextCapsValues,
23    TextFontType,
24};
25use crate::{
26    reader::driver::{
27        get_attribute,
28        xml_read_loop,
29    },
30    structs::StringValue,
31    writer::driver::{
32        write_end_tag,
33        write_start_tag,
34    },
35};
36
37#[derive(Clone, Default, Debug)]
38pub struct RunProperties {
39    text:                 Box<str>,
40    kumimoji:             StringValue,
41    language:             StringValue,
42    alternative_language: StringValue,
43    bold:                 StringValue,
44    sz:                   StringValue,
45    italic:               StringValue,
46    capital:              EnumValue<TextCapsValues>,
47    spacing:              Int32Value,
48    strike:               StringValue,
49    outline:              Option<Box<Outline>>,
50    solid_fill:           Option<Box<SolidFill>>,
51    latin_font:           Option<Box<TextFontType>>,
52    east_asian_font:      Option<Box<TextFontType>>,
53    complex_script_font:  Option<Box<TextFontType>>,
54    gradient_fill:        Option<Box<GradientFill>>,
55    no_fill:              Option<NoFill>,
56    effect_list:          Option<Box<EffectList>>,
57}
58
59impl RunProperties {
60    #[inline]
61    #[must_use]
62    pub fn text(&self) -> &str {
63        &self.text
64    }
65
66    #[inline]
67    #[must_use]
68    #[deprecated(since = "3.0.0", note = "Use text()")]
69    pub fn get_text(&self) -> &str {
70        self.text()
71    }
72
73    #[inline]
74    pub fn set_text<S: Into<String>>(&mut self, value: S) -> &mut Self {
75        self.text = value.into().into_boxed_str();
76        self
77    }
78
79    #[inline]
80    #[must_use]
81    pub fn kumimoji(&self) -> &str {
82        self.kumimoji.value_str()
83    }
84
85    #[inline]
86    #[must_use]
87    #[deprecated(since = "3.0.0", note = "Use kumimoji()")]
88    pub fn get_kumimoji(&self) -> &str {
89        self.kumimoji()
90    }
91
92    #[inline]
93    pub fn set_kumimoji<S: Into<String>>(&mut self, value: S) -> &mut Self {
94        self.kumimoji.set_value_string(value.into());
95        self
96    }
97
98    #[inline]
99    #[must_use]
100    pub fn language(&self) -> &str {
101        self.language.value_str()
102    }
103
104    #[inline]
105    #[must_use]
106    #[deprecated(since = "3.0.0", note = "Use language()")]
107    pub fn get_language(&self) -> &str {
108        self.language()
109    }
110
111    #[inline]
112    pub fn set_language<S: Into<String>>(&mut self, value: S) -> &mut Self {
113        self.language.set_value_string(value.into());
114        self
115    }
116
117    #[inline]
118    #[must_use]
119    pub fn alternative_language(&self) -> &str {
120        self.alternative_language.value_str()
121    }
122
123    #[inline]
124    #[must_use]
125    #[deprecated(since = "3.0.0", note = "Use alternative_language()")]
126    pub fn get_alternative_language(&self) -> &str {
127        self.alternative_language()
128    }
129
130    #[inline]
131    pub fn set_alternative_language<S: Into<String>>(&mut self, value: S) -> &mut Self {
132        self.alternative_language.set_value_string(value.into());
133        self
134    }
135
136    #[inline]
137    #[must_use]
138    pub fn bold(&self) -> &str {
139        self.bold.value_str()
140    }
141
142    #[inline]
143    #[must_use]
144    #[deprecated(since = "3.0.0", note = "Use bold()")]
145    pub fn get_bold(&self) -> &str {
146        self.bold()
147    }
148
149    #[inline]
150    pub fn set_bold<S: Into<String>>(&mut self, value: S) -> &mut Self {
151        self.bold.set_value_string(value.into());
152        self
153    }
154
155    #[inline]
156    #[must_use]
157    pub fn sz(&self) -> &str {
158        self.sz.value_str()
159    }
160
161    #[inline]
162    #[must_use]
163    #[deprecated(since = "3.0.0", note = "Use sz()")]
164    pub fn get_sz(&self) -> &str {
165        self.sz()
166    }
167
168    #[inline]
169    pub fn set_sz<S: Into<String>>(&mut self, value: S) -> &mut Self {
170        self.sz.set_value_string(value.into());
171        self
172    }
173
174    #[inline]
175    #[must_use]
176    pub fn italic(&self) -> &str {
177        self.italic.value_str()
178    }
179
180    #[inline]
181    #[must_use]
182    #[deprecated(since = "3.0.0", note = "Use italic()")]
183    pub fn get_italic(&self) -> &str {
184        self.italic()
185    }
186
187    #[inline]
188    pub fn set_italic<S: Into<String>>(&mut self, value: S) -> &mut Self {
189        self.italic.set_value_string(value.into());
190        self
191    }
192
193    #[inline]
194    #[must_use]
195    pub fn capital(&self) -> &TextCapsValues {
196        self.capital.value()
197    }
198
199    #[inline]
200    #[must_use]
201    #[deprecated(since = "3.0.0", note = "Use capital()")]
202    pub fn get_capital(&self) -> &TextCapsValues {
203        self.capital()
204    }
205
206    #[inline]
207    pub fn set_capital(&mut self, value: TextCapsValues) -> &mut Self {
208        self.capital.set_value(value);
209        self
210    }
211
212    #[inline]
213    #[must_use]
214    pub fn spacing(&self) -> i32 {
215        self.spacing.value()
216    }
217
218    #[inline]
219    #[must_use]
220    #[deprecated(since = "3.0.0", note = "Use spacing()")]
221    pub fn get_spacing(&self) -> i32 {
222        self.spacing()
223    }
224
225    #[inline]
226    pub fn set_spacing(&mut self, value: i32) -> &mut Self {
227        self.spacing.set_value(value);
228        self
229    }
230
231    #[inline]
232    #[must_use]
233    pub fn strike(&self) -> &str {
234        self.strike.value_str()
235    }
236
237    #[inline]
238    #[must_use]
239    #[deprecated(since = "3.0.0", note = "Use strike()")]
240    pub fn get_strike(&self) -> &str {
241        self.strike()
242    }
243
244    #[inline]
245    pub fn set_strike<S: Into<String>>(&mut self, value: S) -> &mut Self {
246        self.strike.set_value_string(value.into());
247        self
248    }
249
250    #[inline]
251    #[must_use]
252    pub fn solid_fill(&self) -> Option<&SolidFill> {
253        self.solid_fill.as_deref()
254    }
255
256    #[inline]
257    #[must_use]
258    #[deprecated(since = "3.0.0", note = "Use solid_fill()")]
259    pub fn get_solid_fill(&self) -> Option<&SolidFill> {
260        self.solid_fill()
261    }
262
263    #[inline]
264    pub fn solid_fill_mut(&mut self) -> Option<&mut SolidFill> {
265        self.solid_fill.as_deref_mut()
266    }
267
268    #[inline]
269    #[deprecated(since = "3.0.0", note = "Use solid_fill_mut()")]
270    pub fn get_solid_fill_mut(&mut self) -> Option<&mut SolidFill> {
271        self.solid_fill_mut()
272    }
273
274    #[inline]
275    pub fn set_solid_fill(&mut self, value: SolidFill) -> &mut Self {
276        self.solid_fill = Some(Box::new(value));
277        self
278    }
279
280    #[inline]
281    #[must_use]
282    pub fn outline(&self) -> Option<&Outline> {
283        self.outline.as_deref()
284    }
285
286    #[inline]
287    #[must_use]
288    #[deprecated(since = "3.0.0", note = "Use outline()")]
289    pub fn get_outline(&self) -> Option<&Outline> {
290        self.outline()
291    }
292
293    #[inline]
294    pub fn outline_mut(&mut self) -> Option<&mut Outline> {
295        self.outline.as_deref_mut()
296    }
297
298    #[inline]
299    #[deprecated(since = "3.0.0", note = "Use outline_mut()")]
300    pub fn get_outline_mut(&mut self) -> Option<&mut Outline> {
301        self.outline_mut()
302    }
303
304    #[inline]
305    pub fn set_outline(&mut self, value: Outline) -> &mut Self {
306        self.outline = Some(Box::new(value));
307        self
308    }
309
310    #[inline]
311    #[must_use]
312    pub fn latin_font(&self) -> Option<&TextFontType> {
313        self.latin_font.as_deref()
314    }
315
316    #[inline]
317    #[must_use]
318    #[deprecated(since = "3.0.0", note = "Use latin_font()")]
319    pub fn get_latin_font(&self) -> Option<&TextFontType> {
320        self.latin_font()
321    }
322
323    #[inline]
324    pub fn latin_font_mut(&mut self) -> Option<&mut TextFontType> {
325        self.latin_font.as_deref_mut()
326    }
327
328    #[inline]
329    #[deprecated(since = "3.0.0", note = "Use latin_font_mut()")]
330    pub fn get_latin_font_mut(&mut self) -> Option<&mut TextFontType> {
331        self.latin_font_mut()
332    }
333
334    #[inline]
335    pub fn set_latin_font(&mut self, value: TextFontType) -> &mut Self {
336        self.latin_font = Some(Box::new(value));
337        self
338    }
339
340    #[inline]
341    #[must_use]
342    pub fn east_asian_font(&self) -> Option<&TextFontType> {
343        self.east_asian_font.as_deref()
344    }
345
346    #[inline]
347    #[must_use]
348    #[deprecated(since = "3.0.0", note = "Use east_asian_font()")]
349    pub fn get_east_asian_font(&self) -> Option<&TextFontType> {
350        self.east_asian_font()
351    }
352
353    #[inline]
354    pub fn east_asian_font_mut(&mut self) -> Option<&mut TextFontType> {
355        self.east_asian_font.as_deref_mut()
356    }
357
358    #[inline]
359    #[deprecated(since = "3.0.0", note = "Use east_asian_font_mut()")]
360    pub fn get_east_asian_font_mut(&mut self) -> Option<&mut TextFontType> {
361        self.east_asian_font_mut()
362    }
363
364    #[inline]
365    pub fn set_east_asian_font(&mut self, value: TextFontType) -> &mut Self {
366        self.east_asian_font = Some(Box::new(value));
367        self
368    }
369
370    #[inline]
371    #[must_use]
372    pub fn complex_script_font(&self) -> Option<&TextFontType> {
373        self.complex_script_font.as_deref()
374    }
375
376    #[inline]
377    #[must_use]
378    #[deprecated(since = "3.0.0", note = "Use complex_script_font()")]
379    pub fn get_complex_script_font(&self) -> Option<&TextFontType> {
380        self.complex_script_font()
381    }
382
383    #[inline]
384    pub fn complex_script_font_mut(&mut self) -> Option<&mut TextFontType> {
385        self.complex_script_font.as_deref_mut()
386    }
387
388    #[inline]
389    #[deprecated(since = "3.0.0", note = "Use complex_script_font_mut()")]
390    pub fn get_complex_script_font_mut(&mut self) -> Option<&mut TextFontType> {
391        self.complex_script_font_mut()
392    }
393
394    #[inline]
395    pub fn set_complex_script_font(&mut self, value: TextFontType) -> &mut Self {
396        self.complex_script_font = Some(Box::new(value));
397        self
398    }
399
400    #[inline]
401    #[must_use]
402    pub fn gradient_fill(&self) -> Option<&GradientFill> {
403        self.gradient_fill.as_deref()
404    }
405
406    #[inline]
407    #[must_use]
408    #[deprecated(since = "3.0.0", note = "Use gradient_fill()")]
409    pub fn get_gradient_fill(&self) -> Option<&GradientFill> {
410        self.gradient_fill()
411    }
412
413    #[inline]
414    pub fn gradient_fill_mut(&mut self) -> Option<&mut GradientFill> {
415        self.gradient_fill.as_deref_mut()
416    }
417
418    #[inline]
419    #[deprecated(since = "3.0.0", note = "Use gradient_fill_mut()")]
420    pub fn get_gradient_fill_mut(&mut self) -> Option<&mut GradientFill> {
421        self.gradient_fill_mut()
422    }
423
424    #[inline]
425    pub fn set_gradient_fill(&mut self, value: GradientFill) -> &mut Self {
426        self.gradient_fill = Some(Box::new(value));
427        self
428    }
429
430    #[inline]
431    #[must_use]
432    pub fn no_fill(&self) -> Option<&NoFill> {
433        self.no_fill.as_ref()
434    }
435
436    #[inline]
437    #[must_use]
438    #[deprecated(since = "3.0.0", note = "Use no_fill()")]
439    pub fn get_no_fill(&self) -> Option<&NoFill> {
440        self.no_fill()
441    }
442
443    #[inline]
444    pub fn no_fill_mut(&mut self) -> Option<&mut NoFill> {
445        self.no_fill.as_mut()
446    }
447
448    #[inline]
449    #[deprecated(since = "3.0.0", note = "Use no_fill_mut()")]
450    pub fn get_no_fill_mut(&mut self) -> Option<&mut NoFill> {
451        self.no_fill_mut()
452    }
453
454    #[inline]
455    pub fn set_no_fill(&mut self, value: NoFill) -> &mut Self {
456        self.no_fill = Some(value);
457        self
458    }
459
460    #[inline]
461    #[must_use]
462    pub fn effect_list(&self) -> Option<&EffectList> {
463        self.effect_list.as_deref()
464    }
465
466    #[inline]
467    #[must_use]
468    #[deprecated(since = "3.0.0", note = "Use effect_list()")]
469    pub fn get_effect_list(&self) -> Option<&EffectList> {
470        self.effect_list()
471    }
472
473    #[inline]
474    pub fn effect_list_mut(&mut self) -> Option<&mut EffectList> {
475        self.effect_list.as_deref_mut()
476    }
477
478    #[inline]
479    #[deprecated(since = "3.0.0", note = "Use effect_list_mut()")]
480    pub fn get_effect_list_mut(&mut self) -> Option<&mut EffectList> {
481        self.effect_list_mut()
482    }
483
484    #[inline]
485    pub fn set_effect_list(&mut self, value: EffectList) -> &mut Self {
486        self.effect_list = Some(Box::new(value));
487        self
488    }
489
490    pub(crate) fn set_attributes<R: std::io::BufRead>(
491        &mut self,
492        reader: &mut Reader<R>,
493        e: &BytesStart,
494        empty_flag: bool,
495    ) {
496        if let Some(v) = get_attribute(e, b"kumimoji") {
497            self.set_kumimoji(v);
498        }
499        if let Some(v) = get_attribute(e, b"lang") {
500            self.set_language(v);
501        }
502        if let Some(v) = get_attribute(e, b"altLang") {
503            self.set_alternative_language(v);
504        }
505        if let Some(v) = get_attribute(e, b"b") {
506            self.set_bold(v);
507        }
508        if let Some(v) = get_attribute(e, b"sz") {
509            self.set_sz(v);
510        }
511        if let Some(v) = get_attribute(e, b"strike") {
512            self.set_strike(v);
513        }
514        if let Some(v) = get_attribute(e, b"i") {
515            self.set_italic(v);
516        }
517        if let Some(v) = get_attribute(e, b"cap") {
518            self.capital.set_value_string(v);
519        }
520        if let Some(v) = get_attribute(e, b"spc") {
521            self.spacing.set_value_string(v);
522        }
523
524        if empty_flag {
525            return;
526        }
527
528        xml_read_loop!(
529            reader,
530            Event::Start(ref e) => {
531                match e.name().into_inner() {
532                b"a:solidFill" => {
533                    let mut obj = SolidFill::default();
534                    obj.set_attributes(reader, e);
535                    self.set_solid_fill(obj);
536                }
537                b"a:ln" => {
538                    let mut obj = Outline::default();
539                    obj.set_attributes(reader, e);
540                    self.set_outline(obj);
541                }
542                b"a:gradFill" => {
543                    let mut obj = GradientFill::default();
544                    obj.set_attributes(reader, e);
545                    self.set_gradient_fill(obj);
546                }
547                b"a:effectLst" => {
548                    let mut effect_list = EffectList::default();
549                    effect_list.set_attributes(reader, e, false);
550                    self.set_effect_list(effect_list);
551                }
552                _ => (),
553                }
554            },
555            Event::Empty(ref e) => {
556                match e.name().into_inner() {
557                b"a:latin" => {
558                    let mut obj = TextFontType::default();
559                    obj.set_attributes(reader, e, true);
560                    self.set_latin_font(obj);
561                }
562                b"a:ea" => {
563                    let mut obj = TextFontType::default();
564                    obj.set_attributes(reader, e, true);
565                    self.set_east_asian_font(obj);
566                }
567                b"a:cs" => {
568                    let mut obj = TextFontType::default();
569                    obj.set_attributes(reader, e, true);
570                    self.set_complex_script_font(obj);
571                }
572                b"a:noFill" => {
573                    let obj = NoFill::default();
574                    NoFill::set_attributes(reader, e, true);
575                    self.set_no_fill(obj);
576                }
577                b"a:effectLst" => {
578                    let mut obj = EffectList::default();
579                    obj.set_attributes(reader, e, true);
580                    self.set_effect_list(obj);
581                }
582                _ => (),
583                }
584            },
585            Event::End(ref e) => {
586                match e.name().into_inner() {
587                    b"a:rPr" | b"a:endParaRPr" | b"a:defRPr" => return,
588                    _ => (),
589                }
590            },
591            Event::Eof => panic!(
592                "Error: Could not find {} end element",
593                "a:rPr, a:endParaRPr, a:defRPr"
594            )
595        );
596    }
597
598    #[inline]
599    pub(crate) fn write_to_rpr(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
600        self.write_to(writer, "a:rPr");
601    }
602
603    #[inline]
604    pub(crate) fn write_to_end_para_rpr(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
605        self.write_to(writer, "a:endParaRPr");
606    }
607
608    #[inline]
609    pub(crate) fn write_to_def_rpr(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
610        self.write_to(writer, "a:defRPr");
611    }
612
613    fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>, tag_name: &str) {
614        let mut attributes: crate::structs::AttrCollection = Vec::new();
615        if self.kumimoji.has_value() {
616            attributes.push(("kumimoji", self.kumimoji.value_str()).into());
617        }
618        if self.language.has_value() {
619            attributes.push(("lang", self.language.value_str()).into());
620        }
621        if self.alternative_language.has_value() {
622            attributes.push(("altLang", self.alternative_language.value_str()).into());
623        }
624        if self.sz.has_value() {
625            attributes.push(("sz", self.sz.value_str()).into());
626        }
627        if self.bold.has_value() {
628            attributes.push(("b", self.bold.value_str()).into());
629        }
630        if self.italic.has_value() {
631            attributes.push(("i", self.italic.value_str()).into());
632        }
633        if self.capital.has_value() {
634            attributes.push(("cap", self.capital.value_string()).into());
635        }
636        let spc = self.spacing.value_string();
637        if self.spacing.has_value() {
638            attributes.push(("spc", &spc).into());
639        }
640        if self.strike.has_value() {
641            attributes.push(("strike", self.strike.value_str()).into());
642        }
643        if self.solid_fill.is_some()
644            || self.outline.is_some()
645            || self.latin_font.is_some()
646            || self.east_asian_font.is_some()
647            || self.gradient_fill.is_some()
648            || self.effect_list.is_some()
649        {
650            write_start_tag(writer, tag_name, attributes, false);
651
652            // a:solidFill
653            if let Some(v) = &self.solid_fill {
654                v.write_to(writer);
655            }
656
657            // a:ln
658            if let Some(v) = &self.outline {
659                v.write_to(writer);
660            }
661
662            // a:latin
663            if let Some(v) = &self.latin_font {
664                v.write_to_latin(writer);
665            }
666
667            // a:ea
668            if let Some(v) = &self.east_asian_font {
669                v.write_to_ea(writer);
670            }
671
672            // a:cs
673            if let Some(v) = &self.complex_script_font {
674                v.write_to_cs(writer);
675            }
676
677            // a:gradFill
678            if let Some(v) = &self.gradient_fill {
679                v.write_to(writer);
680            }
681
682            // a:noFill
683            if self.no_fill.is_some() {
684                NoFill::write_to(writer);
685            }
686
687            // a:effectLst
688            if let Some(v) = &self.effect_list {
689                v.write_to(writer);
690            }
691
692            write_end_tag(writer, tag_name);
693        } else {
694            write_start_tag(writer, tag_name, attributes, true);
695        }
696    }
697}