docx_rs/documents/elements/
table_cell_property.rs1use serde::Serialize;
2use std::io::Write;
3#[cfg(feature = "wasm")]
4use wasm_bindgen::prelude::*;
5
6use super::*;
7use crate::documents::BuildXML;
8use crate::types::*;
9use crate::xml_builder::*;
10
11#[cfg_attr(feature = "wasm", wasm_bindgen)]
12#[derive(Serialize, Debug, Clone, PartialEq, Default)]
13#[serde(rename_all = "camelCase")]
14pub struct TableCellProperty {
15 width: Option<TableCellWidth>,
16 borders: Option<TableCellBorders>,
17 grid_span: Option<GridSpan>,
18 vertical_merge: Option<VMerge>,
19 vertical_align: Option<VAlign>,
20 text_direction: Option<TextDirection>,
21 shading: Option<Shading>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 margins: Option<CellMargins>,
24}
25
26impl TableCellProperty {
27 pub fn new() -> TableCellProperty {
28 Default::default()
29 }
30
31 pub fn width(mut self, v: usize, t: WidthType) -> TableCellProperty {
32 self.width = Some(TableCellWidth::new(v, t));
33 self
34 }
35
36 pub fn vertical_merge(mut self, t: VMergeType) -> TableCellProperty {
37 self.vertical_merge = Some(VMerge::new(t));
38 self
39 }
40
41 pub fn vertical_align(mut self, t: VAlignType) -> TableCellProperty {
42 self.vertical_align = Some(VAlign::new(t));
43 self
44 }
45
46 pub fn text_direction(mut self, t: TextDirectionType) -> Self {
47 self.text_direction = Some(TextDirection::new(t));
48 self
49 }
50
51 pub fn grid_span(mut self, v: usize) -> TableCellProperty {
52 self.grid_span = Some(GridSpan::new(v));
53 self
54 }
55
56 pub fn shading(mut self, s: Shading) -> Self {
57 self.shading = Some(s);
58 self
59 }
60
61 pub fn set_borders(mut self, borders: TableCellBorders) -> Self {
62 self.borders = Some(borders);
63 self
64 }
65
66 pub fn set_border(mut self, border: TableCellBorder) -> Self {
67 self.borders = Some(self.borders.unwrap_or_default().set(border));
68 self
69 }
70
71 pub fn clear_border(mut self, position: TableCellBorderPosition) -> Self {
72 self.borders = Some(self.borders.unwrap_or_default().clear(position));
73 self
74 }
75
76 pub fn clear_all_border(mut self) -> Self {
77 self.borders = Some(self.borders.unwrap_or_default().clear_all());
78 self
79 }
80
81 pub fn margins(mut self, margins: CellMargins) -> Self {
82 self.margins = Some(margins);
83 self
84 }
85
86 pub fn margin_top(mut self, v: usize, t: WidthType) -> Self {
87 if let Some(margins) = self.margins {
88 self.margins = Some(margins.margin_top(v, t));
89 } else {
90 let margins = CellMargins::new();
91 self.margins = Some(margins.margin_top(v, t));
92 }
93 self
94 }
95
96 pub fn margin_right(mut self, v: usize, t: WidthType) -> Self {
97 if let Some(margins) = self.margins {
98 self.margins = Some(margins.margin_right(v, t));
99 } else {
100 let margins = CellMargins::new();
101 self.margins = Some(margins.margin_right(v, t));
102 }
103 self
104 }
105
106 pub fn margin_bottom(mut self, v: usize, t: WidthType) -> Self {
107 if let Some(margins) = self.margins {
108 self.margins = Some(margins.margin_bottom(v, t));
109 } else {
110 let margins = CellMargins::new();
111 self.margins = Some(margins.margin_bottom(v, t));
112 }
113 self
114 }
115
116 pub fn margin_left(mut self, v: usize, t: WidthType) -> Self {
117 if let Some(margins) = self.margins {
118 self.margins = Some(margins.margin_left(v, t));
119 } else {
120 let margins = CellMargins::new();
121 self.margins = Some(margins.margin_left(v, t));
122 }
123 self
124 }
125}
126
127impl BuildXML for TableCellProperty {
128 fn build_to<W: Write>(
129 &self,
130 stream: xml::writer::EventWriter<W>,
131 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
132 XMLBuilder::from(stream)
133 .open_table_cell_property()?
134 .add_optional_child(&self.width)?
135 .add_optional_child(&self.borders)?
136 .add_optional_child(&self.grid_span)?
137 .add_optional_child(&self.vertical_merge)?
138 .add_optional_child(&self.vertical_align)?
139 .add_optional_child(&self.text_direction)?
140 .add_optional_child(&self.shading)?
141 .add_optional_child(&self.margins)?
142 .close()?
143 .into_inner()
144 }
145}
146
147#[cfg(test)]
148mod tests {
149
150 use super::*;
151 #[cfg(test)]
152 use pretty_assertions::assert_eq;
153 use std::str;
154
155 #[test]
156 fn test_default() {
157 let c = TableCellProperty::new();
158 let b = c.build();
159 assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:tcPr />"#);
160 }
161
162 #[test]
163 fn test_grid_span() {
164 let c = TableCellProperty::new().grid_span(3);
165 let b = c.build();
166 assert_eq!(
167 str::from_utf8(&b).unwrap(),
168 r#"<w:tcPr><w:gridSpan w:val="3" /></w:tcPr>"#
169 );
170 }
171
172 #[test]
173 fn test_vmerge() {
174 let c = TableCellProperty::new().vertical_merge(VMergeType::Continue);
175 let b = c.build();
176 assert_eq!(
177 str::from_utf8(&b).unwrap(),
178 r#"<w:tcPr><w:vMerge w:val="continue" /></w:tcPr>"#
179 );
180 }
181
182 #[test]
183 fn test_valign() {
184 let c = TableCellProperty::new().vertical_align(VAlignType::Center);
185 let b = c.build();
186 assert_eq!(
187 str::from_utf8(&b).unwrap(),
188 r#"<w:tcPr><w:vAlign w:val="center" /></w:tcPr>"#
189 );
190 }
191
192 #[test]
193 fn test_shd() {
194 let c = TableCellProperty::new()
195 .shading(Shading::new().shd_type(ShdType::Clear).fill("FF0000"));
196 let b = c.build();
197 assert_eq!(
198 str::from_utf8(&b).unwrap(),
199 r#"<w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FF0000" /></w:tcPr>"#
200 );
201 }
202
203 #[test]
204 fn test_table_cell_prop_json() {
205 let c = TableCellProperty::new()
206 .vertical_merge(VMergeType::Continue)
207 .grid_span(3)
208 .width(200, WidthType::Dxa);
209 assert_eq!(
210 serde_json::to_string(&c).unwrap(),
211 r#"{"width":{"width":200,"widthType":"dxa"},"borders":null,"gridSpan":3,"verticalMerge":"continue","verticalAlign":null,"textDirection":null,"shading":null}"#
212 );
213 }
214
215 #[test]
216 fn test_table_cell_prop_json_with_valign() {
217 let c = TableCellProperty::new().vertical_align(VAlignType::Center);
218 assert_eq!(
219 serde_json::to_string(&c).unwrap(),
220 r#"{"width":null,"borders":null,"gridSpan":null,"verticalMerge":null,"verticalAlign":"center","textDirection":null,"shading":null}"#
221 );
222 }
223}