docx_rs/documents/elements/
table_cell_property.rs

1use 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}