docx_rs/documents/elements/
table_cell.rs1use serde::ser::{SerializeStruct, Serializer};
2use serde::Serialize;
3use std::io::Write;
4
5use super::*;
6use crate::documents::BuildXML;
7use crate::types::*;
8use crate::xml_builder::*;
9
10#[derive(Serialize, Debug, Clone, PartialEq)]
11#[serde(rename_all = "camelCase")]
12pub struct TableCell {
13 pub children: Vec<TableCellContent>,
14 pub property: TableCellProperty,
15 pub has_numbering: bool,
16}
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum TableCellContent {
20 Paragraph(Paragraph),
21 Table(Table),
22 StructuredDataTag(Box<StructuredDataTag>),
23 TableOfContents(Box<TableOfContents>),
24}
25
26impl Serialize for TableCellContent {
27 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28 where
29 S: Serializer,
30 {
31 match *self {
32 TableCellContent::Paragraph(ref s) => {
33 let mut t = serializer.serialize_struct("Paragraph", 2)?;
34 t.serialize_field("type", "paragraph")?;
35 t.serialize_field("data", s)?;
36 t.end()
37 }
38 TableCellContent::Table(ref s) => {
39 let mut t = serializer.serialize_struct("Table", 2)?;
40 t.serialize_field("type", "table")?;
41 t.serialize_field("data", s)?;
42 t.end()
43 }
44 TableCellContent::StructuredDataTag(ref r) => {
45 let mut t = serializer.serialize_struct("StructuredDataTag", 2)?;
46 t.serialize_field("type", "structuredDataTag")?;
47 t.serialize_field("data", r)?;
48 t.end()
49 }
50 TableCellContent::TableOfContents(ref r) => {
51 let mut t = serializer.serialize_struct("TableOfContents", 2)?;
52 t.serialize_field("type", "tableOfContents")?;
53 t.serialize_field("data", r)?;
54 t.end()
55 }
56 }
57 }
58}
59
60impl TableCell {
61 pub fn new() -> TableCell {
62 Default::default()
63 }
64
65 pub fn add_paragraph(mut self, p: Paragraph) -> TableCell {
66 if p.has_numbering {
67 self.has_numbering = true
68 }
69 self.children.push(TableCellContent::Paragraph(p));
70 self
71 }
72
73 pub fn add_table_of_contents(mut self, t: TableOfContents) -> Self {
74 self.children
75 .push(TableCellContent::TableOfContents(Box::new(t)));
76 self
77 }
78
79 pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Self {
80 self.children
81 .push(TableCellContent::StructuredDataTag(Box::new(t)));
82 self
83 }
84
85 pub fn add_table(mut self, t: Table) -> TableCell {
86 if t.has_numbering {
87 self.has_numbering = true
88 }
89 self.children.push(TableCellContent::Table(t));
90 self
91 }
92
93 pub fn vertical_merge(mut self, t: VMergeType) -> TableCell {
94 self.property = self.property.vertical_merge(t);
95 self
96 }
97
98 pub fn shading(mut self, s: Shading) -> TableCell {
99 self.property = self.property.shading(s);
100 self
101 }
102
103 pub fn vertical_align(mut self, t: VAlignType) -> TableCell {
104 self.property = self.property.vertical_align(t);
105 self
106 }
107
108 pub fn text_direction(mut self, t: TextDirectionType) -> TableCell {
109 self.property = self.property.text_direction(t);
110 self
111 }
112
113 pub fn grid_span(mut self, v: usize) -> TableCell {
114 self.property = self.property.grid_span(v);
115 self
116 }
117
118 pub fn width(mut self, v: usize, t: WidthType) -> TableCell {
119 self.property = self.property.width(v, t);
120 self
121 }
122
123 pub fn set_border(mut self, border: TableCellBorder) -> Self {
124 self.property = self.property.set_border(border);
125 self
126 }
127
128 pub fn set_borders(mut self, borders: TableCellBorders) -> Self {
129 self.property = self.property.set_borders(borders);
130 self
131 }
132
133 pub fn clear_border(mut self, position: TableCellBorderPosition) -> Self {
134 self.property = self.property.clear_border(position);
135 self
136 }
137
138 pub fn clear_all_border(mut self) -> Self {
139 self.property = self.property.clear_all_border();
140 self
141 }
142}
143
144impl Default for TableCell {
145 fn default() -> Self {
146 let property = TableCellProperty::new();
147 let children = vec![];
148 Self {
149 property,
150 children,
151 has_numbering: false,
152 }
153 }
154}
155
156impl BuildXML for TableCell {
157 fn build_to<W: Write>(
158 &self,
159 stream: xml::writer::EventWriter<W>,
160 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
161 XMLBuilder::from(stream)
162 .open_table_cell()?
163 .add_child(&self.property)?
164 .apply_each(&self.children, |ch, b| {
165 match ch {
166 TableCellContent::Paragraph(p) => b.add_child(p),
167 TableCellContent::Table(t) => {
168 b.add_child(t)?
169 .apply_if(self.children.len() == 1, |b| b.add_child(&Paragraph::new()))
171 }
172 TableCellContent::StructuredDataTag(t) => b.add_child(&t),
173 TableCellContent::TableOfContents(t) => b.add_child(&t),
174 }
175 })?
176 .apply_if(self.children.is_empty(), |b| b.add_child(&Paragraph::new()))?
178 .close()?
179 .into_inner()
180 }
181}
182
183#[cfg(test)]
184mod tests {
185
186 use super::*;
187 #[cfg(test)]
188 use pretty_assertions::assert_eq;
189 use std::str;
190
191 #[test]
192 fn test_cell() {
193 let b = TableCell::new().build();
194 assert_eq!(
195 str::from_utf8(&b).unwrap(),
196 r#"<w:tc><w:tcPr /><w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr></w:p></w:tc>"#
197 );
198 }
199
200 #[test]
201 fn test_cell_add_p() {
202 let b = TableCell::new()
203 .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
204 .build();
205 assert_eq!(
206 str::from_utf8(&b).unwrap(),
207 r#"<w:tc><w:tcPr /><w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:t xml:space="preserve">Hello</w:t></w:r></w:p></w:tc>"#
208 );
209 }
210
211 #[test]
212 fn test_cell_json() {
213 let c = TableCell::new()
214 .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
215 .grid_span(2);
216 assert_eq!(
217 serde_json::to_string(&c).unwrap(),
218 r#"{"children":[{"type":"paragraph","data":{"id":"12345678","children":[{"type":"run","data":{"runProperty":{},"children":[{"type":"text","data":{"preserveSpace":true,"text":"Hello"}}]}}],"property":{"runProperty":{},"tabs":[]},"hasNumbering":false}}],"property":{"width":null,"borders":null,"gridSpan":2,"verticalMerge":null,"verticalAlign":null,"textDirection":null,"shading":null},"hasNumbering":false}"#,
219 );
220 }
221}