umya_spreadsheet/structs/
border.rs

1// left right top bottom
2use super::BorderStyleValues;
3use super::Color;
4use super::EnumValue;
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 Border {
15    color: Color,
16    style: EnumValue<BorderStyleValues>,
17}
18
19impl Border {
20    #[inline]
21    pub fn get_color(&self) -> &Color {
22        &self.color
23    }
24
25    #[inline]
26    pub fn get_color_mut(&mut self) -> &mut Color {
27        &mut self.color
28    }
29
30    #[inline]
31    pub fn set_color(&mut self, value: Color) -> &mut Self {
32        self.color = value;
33        self
34    }
35
36    #[inline]
37    pub fn get_style(&self) -> &BorderStyleValues {
38        self.style.get_value()
39    }
40
41    #[inline]
42    pub fn set_style(&mut self, value: BorderStyleValues) -> &mut Self {
43        self.style.set_value(value);
44        self
45    }
46
47    // Border style
48    pub const BORDER_NONE: &'static str = "none";
49    pub const BORDER_DASHDOT: &'static str = "dashDot";
50    pub const BORDER_DASHDOTDOT: &'static str = "dashDotDot";
51    pub const BORDER_DASHED: &'static str = "dashed";
52    pub const BORDER_DOTTED: &'static str = "dotted";
53    pub const BORDER_DOUBLE: &'static str = "double";
54    pub const BORDER_HAIR: &'static str = "hair";
55    pub const BORDER_MEDIUM: &'static str = "medium";
56    pub const BORDER_MEDIUMDASHDOT: &'static str = "mediumDashDot";
57    pub const BORDER_MEDIUMDASHDOTDOT: &'static str = "mediumDashDotDot";
58    pub const BORDER_MEDIUMDASHED: &'static str = "mediumDashed";
59    pub const BORDER_SLANTDASHDOT: &'static str = "slantDashDot";
60    pub const BORDER_THICK: &'static str = "thick";
61    pub const BORDER_THIN: &'static str = "thin";
62
63    #[inline]
64    pub fn get_border_style(&self) -> &str {
65        self.style.get_value_string()
66    }
67    #[inline]
68    pub fn set_border_style<S: Into<String>>(&mut self, value: S) {
69        self.style.set_value_string(value);
70    }
71
72    pub(crate) fn get_hash_code(&self) -> String {
73        format!(
74            "{:x}",
75            md5::Md5::digest(format!(
76                "{}{}",
77                &self.style.get_value_string(),
78                &self.get_color().get_hash_code()
79            ))
80        )
81    }
82
83    // When opened in software such as Excel, it is visually blank.
84    #[inline]
85    pub(crate) fn is_visually_empty(&self) -> bool {
86        self.style.get_value() == &BorderStyleValues::None
87    }
88
89    pub(crate) fn set_attributes<R: std::io::BufRead>(
90        &mut self,
91        reader: &mut Reader<R>,
92        e: &BytesStart,
93        empty_flg: bool,
94    ) {
95        set_string_from_xml!(self, e, style, "style");
96
97        if empty_flg {
98            return;
99        }
100
101        xml_read_loop!(
102            reader,
103            Event::Empty(ref e) => {
104                if e.name().into_inner() == b"color" {
105                    self.color.set_attributes(reader, e, true);
106                }
107            },
108            Event::End(ref e) => {
109                match e.name().into_inner() {
110                    b"left" => return,
111                    b"right" => return,
112                    b"top" => return,
113                    b"bottom" => return,
114                    b"diagonal" => return,
115                    b"vertical" => return,
116                    b"horizontal" => return,
117                    _ => (),
118                }
119            },
120            Event::Eof => panic!(
121                "Error: Could not find {} end element",
122                "left,right,top,bottom,diagonal,vertical,horizontal"
123            )
124        );
125    }
126
127    #[inline]
128    pub(crate) fn write_to_left(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
129        self.write_to(writer, "left");
130    }
131
132    #[inline]
133    pub(crate) fn write_to_right(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
134        self.write_to(writer, "right");
135    }
136
137    #[inline]
138    pub(crate) fn write_to_top(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
139        self.write_to(writer, "top");
140    }
141
142    #[inline]
143    pub(crate) fn write_to_bottom(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
144        self.write_to(writer, "bottom");
145    }
146
147    #[inline]
148    pub(crate) fn write_to_diagonal(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
149        self.write_to(writer, "diagonal");
150    }
151
152    #[inline]
153    pub(crate) fn write_to_vertical(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
154        self.write_to(writer, "vertical");
155    }
156
157    #[inline]
158    pub(crate) fn write_to_horizontal(&self, writer: &mut Writer<Cursor<Vec<u8>>>) {
159        self.write_to(writer, "horizontal");
160    }
161
162    pub(crate) fn write_to(&self, writer: &mut Writer<Cursor<Vec<u8>>>, tag_name: &str) {
163        // left,right,top,bottom,diagonal,vertical,horizontal
164        let mut attributes: Vec<(&str, &str)> = Vec::new();
165        if self.style.has_value() {
166            attributes.push(("style", self.style.get_value_string()));
167        }
168
169        let empty_flag = !self.color.has_value();
170        write_start_tag(writer, tag_name, attributes, empty_flag);
171
172        if !empty_flag {
173            // color
174            self.color.write_to_color(writer);
175
176            write_end_tag(writer, tag_name);
177        }
178    }
179}