Skip to main content

umya_spreadsheet/structs/
pattern_fill.rs

1// patternFill
2use std::io::Cursor;
3
4use md5::Digest;
5use quick_xml::{
6    Reader,
7    Writer,
8    events::{
9        BytesStart,
10        Event,
11    },
12};
13
14use super::{
15    Color,
16    EnumValue,
17    PatternValues,
18};
19use crate::{
20    reader::driver::{
21        get_attribute,
22        set_string_from_xml,
23        xml_read_loop,
24    },
25    writer::driver::{
26        write_end_tag,
27        write_start_tag,
28    },
29};
30
31#[derive(Default, Debug, Clone, PartialEq, PartialOrd)]
32pub struct PatternFill {
33    pub(crate) pattern_type: EnumValue<PatternValues>,
34    foreground_color:        Option<Box<Color>>,
35    background_color:        Option<Box<Color>>,
36}
37
38impl PatternFill {
39    #[inline]
40    #[must_use]
41    pub fn pattern_type(&self) -> &PatternValues {
42        self.pattern_type.value()
43    }
44
45    #[inline]
46    #[must_use]
47    #[deprecated(since = "3.0.0", note = "Use pattern_type()")]
48    pub fn get_pattern_type(&self) -> &PatternValues {
49        self.pattern_type()
50    }
51
52    #[inline]
53    pub fn set_pattern_type(&mut self, value: PatternValues) -> &mut Self {
54        self.pattern_type.set_value(value);
55        self
56    }
57
58    fn auto_set_pattern_type(&mut self) -> &mut Self {
59        if self.pattern_type() == &PatternValues::None {
60            if self.foreground_color().is_some() {
61                self.set_pattern_type(PatternValues::Solid);
62            }
63        } else if self.foreground_color().is_none() {
64            self.set_pattern_type(PatternValues::None);
65        }
66        self
67    }
68
69    #[inline]
70    #[must_use]
71    pub fn foreground_color(&self) -> Option<&Color> {
72        self.foreground_color.as_deref()
73    }
74
75    #[inline]
76    #[must_use]
77    #[deprecated(since = "3.0.0", note = "Use foreground_color()")]
78    pub fn get_foreground_color(&self) -> Option<&Color> {
79        self.foreground_color()
80    }
81
82    #[inline]
83    pub fn foreground_color_mut(&mut self) -> &mut Color {
84        self.foreground_color
85            .get_or_insert(Box::new(Color::default()))
86    }
87
88    #[inline]
89    #[deprecated(since = "3.0.0", note = "Use foreground_color_mut()")]
90    pub fn get_foreground_color_mut(&mut self) -> &mut Color {
91        self.foreground_color_mut()
92    }
93
94    #[inline]
95    pub fn set_foreground_color(&mut self, value: Color) -> &mut Self {
96        self.foreground_color = Some(Box::new(value));
97        self.auto_set_pattern_type();
98        self
99    }
100
101    #[inline]
102    pub fn remove_foreground_color(&mut self) -> &mut Self {
103        self.foreground_color = None;
104        self
105    }
106
107    #[inline]
108    #[must_use]
109    pub fn background_color(&self) -> Option<&Color> {
110        self.background_color.as_deref()
111    }
112
113    #[inline]
114    #[must_use]
115    #[deprecated(since = "3.0.0", note = "Use background_color()")]
116    pub fn get_background_color(&self) -> Option<&Color> {
117        self.background_color()
118    }
119
120    #[inline]
121    pub fn background_color_mut(&mut self) -> &mut Color {
122        self.background_color
123            .get_or_insert(Box::new(Color::default()))
124    }
125
126    #[inline]
127    #[deprecated(since = "3.0.0", note = "Use background_color_mut()")]
128    pub fn get_background_color_mut(&mut self) -> &mut Color {
129        self.background_color_mut()
130    }
131
132    #[inline]
133    pub fn set_background_color(&mut self, value: Color) -> &mut Self {
134        self.background_color = Some(Box::new(value));
135        self
136    }
137
138    #[inline]
139    pub fn remove_background_color(&mut self) -> &mut Self {
140        self.background_color = None;
141        self
142    }
143
144    pub(crate) fn hash_code(&self) -> String {
145        let pattern_type = self.pattern_type.value_string();
146        let foreground_color = self
147            .foreground_color
148            .as_ref()
149            .map_or("None".into(), |v| v.hash_code());
150        let background_color = self
151            .background_color
152            .as_ref()
153            .map_or("None".into(), |v| v.hash_code());
154        format!(
155            "{:x}",
156            md5::Md5::digest(format!(
157                "{pattern_type}{foreground_color}{background_color}"
158            ))
159        )
160    }
161
162    #[deprecated(since = "3.0.0", note = "Use hash_code()")]
163    pub(crate) fn get_hash_code(&self) -> String {
164        self.hash_code()
165    }
166
167    // When opened in software such as Excel, it is visually blank.
168    pub(crate) fn is_visually_empty(&self) -> bool {
169        !(self.pattern_type.value() != &PatternValues::None
170            || self
171                .foreground_color
172                .as_ref()
173                .is_some_and(|x| !x.is_visually_empty())
174            || self
175                .background_color
176                .as_ref()
177                .is_some_and(|x| x.is_visually_empty()))
178    }
179
180    pub(crate) fn set_attributes<R: std::io::BufRead>(
181        &mut self,
182        reader: &mut Reader<R>,
183        e: &BytesStart,
184        empty_flag: bool,
185    ) {
186        set_string_from_xml!(self, e, pattern_type, "patternType");
187
188        if empty_flag {
189            return;
190        }
191
192        xml_read_loop!(
193            reader,
194            Event::Empty(ref e) => {
195                match e.name().into_inner() {
196                    b"fgColor" => {
197                        let mut obj = Color::default();
198                        obj.set_attributes(reader, e, true);
199                        self.set_foreground_color(obj);
200                    }
201                    b"bgColor" => {
202                        let mut obj = Color::default();
203                        obj.set_attributes(reader, e, true);
204                        self.set_background_color(obj);
205                    }
206                    _ => (),
207                }
208            },
209            Event::End(ref e) => {
210                if e.name().into_inner() == b"patternFill" {
211                    return
212                }
213            },
214            Event::Eof => panic!("Error: Could not find {} end element", "patternFill")
215        );
216    }
217
218    pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
219        let empty_flag = self.foreground_color.is_none() && self.background_color.is_none();
220
221        // patternFill
222        let mut attributes: crate::structs::AttrCollection = Vec::new();
223        if self.pattern_type.has_value() {
224            attributes.push(("patternType", self.pattern_type.value_string()).into());
225        }
226        write_start_tag(writer, "patternFill", attributes, empty_flag);
227
228        if !empty_flag {
229            // fgColor
230            if let Some(v) = &self.foreground_color {
231                v.write_to_fg_color(writer);
232            }
233
234            // bgColor
235            if let Some(v) = &self.background_color {
236                v.write_to_bg_color(writer);
237            }
238
239            write_end_tag(writer, "patternFill");
240        }
241    }
242}