umya_spreadsheet/structs/
pattern_fill.rs1use super::Color;
3use super::EnumValue;
4use super::PatternValues;
5use crate::reader::driver::*;
6use crate::writer::driver::*;
7use md5::Digest;
8use quick_xml::events::{BytesStart, Event};
9use quick_xml::Reader;
10use quick_xml::Writer;
11use std::io::Cursor;
12
13#[derive(Default, Debug, Clone, PartialEq, PartialOrd)]
14pub struct PatternFill {
15 pub(crate) pattern_type: EnumValue<PatternValues>,
16 foreground_color: Option<Box<Color>>,
17 background_color: Option<Box<Color>>,
18}
19
20impl PatternFill {
21 #[inline]
22 pub fn get_pattern_type(&self) -> &PatternValues {
23 self.pattern_type.get_value()
24 }
25
26 #[inline]
27 pub fn set_pattern_type(&mut self, value: PatternValues) -> &mut Self {
28 self.pattern_type.set_value(value);
29 self
30 }
31
32 fn auto_set_pattern_type(&mut self) -> &mut Self {
33 if self.get_pattern_type() == &PatternValues::None {
34 if self.get_foreground_color().is_some() {
35 self.set_pattern_type(PatternValues::Solid);
36 }
37 } else if self.get_foreground_color().is_none() {
38 self.set_pattern_type(PatternValues::None);
39 }
40 self
41 }
42
43 #[inline]
44 pub fn get_foreground_color(&self) -> Option<&Color> {
45 self.foreground_color.as_deref()
46 }
47
48 #[inline]
49 pub fn get_foreground_color_mut(&mut self) -> &mut Color {
50 self.foreground_color
51 .get_or_insert(Box::new(Color::default()))
52 }
53
54 #[inline]
55 pub fn set_foreground_color(&mut self, value: Color) -> &mut Self {
56 self.foreground_color = Some(Box::new(value));
57 self.auto_set_pattern_type();
58 self
59 }
60
61 #[inline]
62 pub fn remove_foreground_color(&mut self) -> &mut Self {
63 self.foreground_color = None;
64 self
65 }
66
67 #[inline]
68 pub fn get_background_color(&self) -> Option<&Color> {
69 self.background_color.as_deref()
70 }
71
72 #[inline]
73 pub fn get_background_color_mut(&mut self) -> &mut Color {
74 self.background_color
75 .get_or_insert(Box::new(Color::default()))
76 }
77
78 #[inline]
79 pub fn set_background_color(&mut self, value: Color) -> &mut Self {
80 self.background_color = Some(Box::new(value));
81 self
82 }
83
84 #[inline]
85 pub fn remove_background_color(&mut self) -> &mut Self {
86 self.background_color = None;
87 self
88 }
89
90 pub(crate) fn get_hash_code(&self) -> String {
91 let pattern_type = self.pattern_type.get_value_string();
92 let foreground_color = self
93 .foreground_color
94 .as_ref()
95 .map_or("None".into(), |v| v.get_hash_code());
96 let background_color = self
97 .background_color
98 .as_ref()
99 .map_or("None".into(), |v| v.get_hash_code());
100 format!(
101 "{:x}",
102 md5::Md5::digest(format!(
103 "{}{}{}",
104 pattern_type, foreground_color, background_color
105 ))
106 )
107 }
108
109 pub(crate) fn is_visually_empty(&self) -> bool {
111 !(self.pattern_type.get_value() != &PatternValues::None
112 || self
113 .foreground_color
114 .as_ref()
115 .is_some_and(|x| !x.is_visually_empty())
116 || self
117 .background_color
118 .as_ref()
119 .is_some_and(|x| x.is_visually_empty()))
120 }
121
122 pub(crate) fn set_attributes<R: std::io::BufRead>(
123 &mut self,
124 reader: &mut Reader<R>,
125 e: &BytesStart,
126 empty_flag: bool,
127 ) {
128 set_string_from_xml!(self, e, pattern_type, "patternType");
129
130 if empty_flag {
131 return;
132 }
133
134 xml_read_loop!(
135 reader,
136 Event::Empty(ref e) => {
137 match e.name().into_inner() {
138 b"fgColor" => {
139 let mut obj = Color::default();
140 obj.set_attributes(reader, e, true);
141 self.set_foreground_color(obj);
142 }
143 b"bgColor" => {
144 let mut obj = Color::default();
145 obj.set_attributes(reader, e, true);
146 self.set_background_color(obj);
147 }
148 _ => (),
149 }
150 },
151 Event::End(ref e) => {
152 if e.name().into_inner() == b"patternFill" {
153 return
154 }
155 },
156 Event::Eof => panic!("Error: Could not find {} end element", "patternFill")
157 );
158 }
159
160 pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
161 let empty_flag = self.foreground_color.is_none() && self.background_color.is_none();
162
163 let mut attributes: Vec<(&str, &str)> = Vec::new();
165 if self.pattern_type.has_value() {
166 attributes.push(("patternType", self.pattern_type.get_value_string()));
167 }
168 write_start_tag(writer, "patternFill", attributes, empty_flag);
169
170 if !empty_flag {
171 if let Some(v) = &self.foreground_color {
173 v.write_to_fg_color(writer);
174 }
175
176 if let Some(v) = &self.background_color {
178 v.write_to_bg_color(writer);
179 }
180
181 write_end_tag(writer, "patternFill");
182 }
183 }
184}