umya_spreadsheet/structs/
pattern_fill.rs1use 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 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 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 if let Some(v) = &self.foreground_color {
231 v.write_to_fg_color(writer);
232 }
233
234 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}