umya_spreadsheet/structs/
pattern_fill.rs1use 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 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 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 if let Some(v) = &self.foreground_color {
227 v.write_to_fg_color(writer);
228 }
229
230 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}