Skip to main content

umya_spreadsheet/structs/
pattern_fill.rs

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