docx_rs/documents/elements/
table_borders.rs1use serde::Serialize;
2use std::io::Write;
3
4use crate::documents::BuildXML;
5use crate::types::*;
6use crate::xml_builder::*;
7
8#[derive(Serialize, Debug, Clone, PartialEq)]
21#[serde(rename_all = "camelCase")]
22pub struct TableBorder {
23 pub border_type: BorderType,
24 pub size: usize,
25 pub color: String,
26 position: TableBorderPosition,
27 space: usize,
28}
29
30impl TableBorder {
31 pub fn new(position: TableBorderPosition) -> TableBorder {
32 TableBorder {
33 position,
34 border_type: BorderType::Single,
35 size: 2,
36 space: 0,
37 color: "000000".to_owned(),
38 }
39 }
40
41 pub fn color(mut self, color: impl Into<String>) -> TableBorder {
42 self.color = color.into();
43 self
44 }
45
46 pub fn size(mut self, size: usize) -> TableBorder {
47 self.size = size;
48 self
49 }
50
51 pub fn border_type(mut self, border_type: BorderType) -> TableBorder {
52 self.border_type = border_type;
53 self
54 }
55}
56
57impl BuildXML for TableBorder {
58 fn build_to<W: Write>(
59 &self,
60 stream: xml::writer::EventWriter<W>,
61 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
62 let func = match self.position {
63 TableBorderPosition::Top => XMLBuilder::border_top,
64 TableBorderPosition::Left => XMLBuilder::border_left,
65 TableBorderPosition::Bottom => XMLBuilder::border_bottom,
66 TableBorderPosition::Right => XMLBuilder::border_right,
67 TableBorderPosition::InsideH => XMLBuilder::border_inside_h,
68 TableBorderPosition::InsideV => XMLBuilder::border_inside_v,
69 };
70
71 XMLBuilder::from(stream)
72 .apply(|b| func(b, self.border_type, self.size, self.space, &self.color))?
73 .into_inner()
74 }
75}
76
77#[derive(Serialize, Debug, Clone, PartialEq)]
78#[serde(rename_all = "camelCase")]
79pub struct TableBorders {
80 top: Option<TableBorder>,
81 left: Option<TableBorder>,
82 bottom: Option<TableBorder>,
83 right: Option<TableBorder>,
84 inside_h: Option<TableBorder>,
85 inside_v: Option<TableBorder>,
86}
87
88impl Default for TableBorders {
89 fn default() -> TableBorders {
90 TableBorders {
91 top: Some(TableBorder::new(TableBorderPosition::Top)),
92 left: Some(TableBorder::new(TableBorderPosition::Left)),
93 bottom: Some(TableBorder::new(TableBorderPosition::Bottom)),
94 right: Some(TableBorder::new(TableBorderPosition::Right)),
95 inside_h: Some(TableBorder::new(TableBorderPosition::InsideH)),
96 inside_v: Some(TableBorder::new(TableBorderPosition::InsideV)),
97 }
98 }
99}
100
101impl TableBorders {
102 pub fn new() -> TableBorders {
103 Default::default()
104 }
105
106 pub fn with_empty() -> TableBorders {
107 TableBorders {
108 top: None,
109 left: None,
110 bottom: None,
111 right: None,
112 inside_h: None,
113 inside_v: None,
114 }
115 }
116
117 pub fn set(mut self, border: TableBorder) -> Self {
118 match border.position {
119 TableBorderPosition::Top => self.top = Some(border),
120 TableBorderPosition::Left => self.left = Some(border),
121 TableBorderPosition::Bottom => self.bottom = Some(border),
122 TableBorderPosition::Right => self.right = Some(border),
123 TableBorderPosition::InsideH => self.inside_h = Some(border),
124 TableBorderPosition::InsideV => self.inside_v = Some(border),
125 };
126 self
127 }
128
129 pub fn clear(mut self, position: TableBorderPosition) -> Self {
130 let nil = TableBorder::new(position.clone()).border_type(BorderType::Nil);
131 match position {
132 TableBorderPosition::Top => self.top = Some(nil),
133 TableBorderPosition::Left => self.left = Some(nil),
134 TableBorderPosition::Bottom => self.bottom = Some(nil),
135 TableBorderPosition::Right => self.right = Some(nil),
136 TableBorderPosition::InsideH => self.inside_h = Some(nil),
137 TableBorderPosition::InsideV => self.inside_v = Some(nil),
138 };
139 self
140 }
141
142 pub fn clear_all(mut self) -> Self {
143 self.top = Some(TableBorder::new(TableBorderPosition::Top).border_type(BorderType::Nil));
144 self.left = Some(TableBorder::new(TableBorderPosition::Left).border_type(BorderType::Nil));
145 self.bottom =
146 Some(TableBorder::new(TableBorderPosition::Bottom).border_type(BorderType::Nil));
147 self.right =
148 Some(TableBorder::new(TableBorderPosition::Right).border_type(BorderType::Nil));
149 self.inside_h =
150 Some(TableBorder::new(TableBorderPosition::InsideH).border_type(BorderType::Nil));
151 self.inside_v =
152 Some(TableBorder::new(TableBorderPosition::InsideV).border_type(BorderType::Nil));
153 self
154 }
155}
156
157impl BuildXML for TableBorders {
158 fn build_to<W: Write>(
159 &self,
160 stream: xml::writer::EventWriter<W>,
161 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
162 XMLBuilder::from(stream)
163 .open_table_borders()?
164 .add_optional_child(&self.top)?
165 .add_optional_child(&self.left)?
166 .add_optional_child(&self.bottom)?
167 .add_optional_child(&self.right)?
168 .add_optional_child(&self.inside_h)?
169 .add_optional_child(&self.inside_v)?
170 .close()?
171 .into_inner()
172 }
173}
174
175#[cfg(test)]
176mod tests {
177
178 use super::*;
179 #[cfg(test)]
180 use pretty_assertions::assert_eq;
181 use std::str;
182
183 #[test]
184 fn test_table_borders() {
185 let b = TableBorders::new().build();
186 assert_eq!(
187 str::from_utf8(&b).unwrap(),
188 r#"<w:tblBorders><w:top w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:left w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:bottom w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:right w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:insideH w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:insideV w:val="single" w:sz="2" w:space="0" w:color="000000" /></w:tblBorders>"#
189 );
190 }
191
192 #[test]
193 fn test_table_borders_set() {
194 let b = TableBorders::new()
195 .set(TableBorder::new(TableBorderPosition::Left).color("AAAAAA"))
196 .clear(TableBorderPosition::Top)
197 .build();
198 assert_eq!(
199 str::from_utf8(&b).unwrap(),
200 r#"<w:tblBorders><w:top w:val="nil" w:sz="2" w:space="0" w:color="000000" /><w:left w:val="single" w:sz="2" w:space="0" w:color="AAAAAA" /><w:bottom w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:right w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:insideH w:val="single" w:sz="2" w:space="0" w:color="000000" /><w:insideV w:val="single" w:sz="2" w:space="0" w:color="000000" /></w:tblBorders>"#
201 );
202 }
203}