docx_rs/documents/elements/
section_property.rs

1use super::*;
2use crate::documents::BuildXML;
3use crate::types::*;
4use crate::xml_builder::*;
5use crate::{Footer, Header};
6
7use serde::Serialize;
8
9#[derive(Debug, Clone, PartialEq, Serialize)]
10#[serde(rename_all = "camelCase")]
11pub struct SectionProperty {
12    pub page_size: PageSize,
13    pub page_margin: PageMargin,
14    pub columns: usize,
15    pub space: usize,
16    pub title_pg: bool,
17    pub text_direction: String,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub doc_grid: Option<DocGrid>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub header_reference: Option<HeaderReference>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub header: Option<Header>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub first_header_reference: Option<HeaderReference>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub first_header: Option<Header>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub even_header_reference: Option<HeaderReference>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub even_header: Option<Header>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub footer_reference: Option<FooterReference>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub footer: Option<Footer>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub first_footer_reference: Option<FooterReference>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub first_footer: Option<Footer>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub even_footer_reference: Option<FooterReference>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub even_footer: Option<Footer>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub section_type: Option<SectionType>,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub page_num_type: Option<PageNumType>,
48}
49
50impl SectionProperty {
51    pub fn new() -> SectionProperty {
52        Default::default()
53    }
54
55    pub fn page_size(mut self, size: PageSize) -> Self {
56        self.page_size = size;
57        self
58    }
59
60    pub fn page_margin(mut self, margin: PageMargin) -> Self {
61        self.page_margin = margin;
62        self
63    }
64
65    pub fn page_orient(mut self, o: PageOrientationType) -> Self {
66        self.page_size = self.page_size.orient(o);
67        self
68    }
69
70    pub fn doc_grid(mut self, doc_grid: DocGrid) -> Self {
71        self.doc_grid = Some(doc_grid);
72        self
73    }
74
75    pub fn text_direction(mut self, direction: String) -> Self {
76        self.text_direction = direction;
77        self
78    }
79
80    pub fn title_pg(mut self) -> Self {
81        self.title_pg = true;
82        self
83    }
84
85    pub fn header(mut self, h: Header, rid: &str) -> Self {
86        self.header_reference = Some(HeaderReference::new("default", rid));
87        self.header = Some(h);
88        self
89    }
90
91    pub fn first_header(mut self, h: Header, rid: &str) -> Self {
92        self.first_header_reference = Some(HeaderReference::new("first", rid));
93        self.first_header = Some(h);
94        self.title_pg = true;
95        self
96    }
97
98    pub fn first_header_without_title_pg(mut self, h: Header, rid: &str) -> Self {
99        self.first_header_reference = Some(HeaderReference::new("first", rid));
100        self.first_header = Some(h);
101        self
102    }
103
104    pub fn even_header(mut self, h: Header, rid: &str) -> Self {
105        self.even_header_reference = Some(HeaderReference::new("even", rid));
106        self.even_header = Some(h);
107        self
108    }
109
110    pub fn footer(mut self, h: Footer, rid: &str) -> Self {
111        self.footer_reference = Some(FooterReference::new("default", rid));
112        self.footer = Some(h);
113        self
114    }
115
116    pub fn first_footer(mut self, h: Footer, rid: &str) -> Self {
117        self.first_footer_reference = Some(FooterReference::new("first", rid));
118        self.first_footer = Some(h);
119        self.title_pg = true;
120        self
121    }
122
123    pub fn first_footer_without_title_pg(mut self, h: Footer, rid: &str) -> Self {
124        self.first_footer_reference = Some(FooterReference::new("first", rid));
125        self.first_footer = Some(h);
126        self
127    }
128
129    pub fn even_footer(mut self, h: Footer, rid: &str) -> Self {
130        self.even_footer_reference = Some(FooterReference::new("even", rid));
131        self.even_footer = Some(h);
132        self
133    }
134
135    pub fn get_headers(&self) -> Vec<&Header> {
136        let mut headers = vec![];
137        if let Some(ref header) = self.header {
138            headers.push(header);
139        }
140        if let Some(ref header) = self.first_header {
141            headers.push(header);
142        }
143        if let Some(ref header) = self.even_header {
144            headers.push(header);
145        }
146        headers
147    }
148
149    pub fn get_footers(&self) -> Vec<&Footer> {
150        let mut footers = vec![];
151        if let Some(ref footer) = self.footer {
152            footers.push(footer);
153        }
154        if let Some(ref footer) = self.first_footer {
155            footers.push(footer);
156        }
157        if let Some(ref footer) = self.even_footer {
158            footers.push(footer);
159        }
160        footers
161    }
162
163    pub fn page_num_type(mut self, h: PageNumType) -> Self {
164        self.page_num_type = Some(h);
165        self
166    }
167}
168
169impl Default for SectionProperty {
170    fn default() -> Self {
171        Self {
172            page_size: PageSize::new(),
173            page_margin: PageMargin::new(),
174            columns: 1,
175            space: 425,
176            title_pg: false,
177            text_direction: "lrTb".to_string(),
178            doc_grid: None,
179            // headers
180            header_reference: None,
181            header: None,
182            first_header_reference: None,
183            first_header: None,
184            even_header_reference: None,
185            even_header: None,
186            // footers
187            footer_reference: None,
188            footer: None,
189            first_footer_reference: None,
190            first_footer: None,
191            even_footer_reference: None,
192            even_footer: None,
193            section_type: None,
194            page_num_type: None,
195        }
196    }
197}
198
199impl BuildXML for SectionProperty {
200    fn build(&self) -> Vec<u8> {
201        let mut b = XMLBuilder::new();
202        b = b
203            .open_section_property()
204            .add_child(&self.page_size)
205            .add_child(&self.page_margin)
206            .columns(&format!("{}", &self.space), &format!("{}", &self.columns))
207            .add_optional_child(&self.doc_grid)
208            .add_optional_child(&self.header_reference)
209            .add_optional_child(&self.first_header_reference)
210            .add_optional_child(&self.even_header_reference)
211            .add_optional_child(&self.footer_reference)
212            .add_optional_child(&self.first_footer_reference)
213            .add_optional_child(&self.even_footer_reference)
214            .add_optional_child(&self.page_num_type);
215
216        if !self.text_direction.eq("lrTb") {
217            b = b.text_direction(&self.text_direction);
218        }
219        if let Some(t) = self.section_type {
220            b = b.type_tag(&t.to_string());
221        }
222
223        if self.title_pg {
224            b = b.title_pg();
225        }
226
227        b.close().build()
228    }
229}
230
231#[cfg(test)]
232mod tests {
233
234    use super::*;
235    #[cfg(test)]
236    use pretty_assertions::assert_eq;
237    use std::str;
238
239    #[test]
240    fn text_section_text_direction() {
241        let mut c = SectionProperty::new();
242        c = c.text_direction("tbRl".to_string());
243        let b = c.build();
244        assert_eq!(
245            str::from_utf8(&b).unwrap(),
246            r#"<w:sectPr><w:pgSz w:w="11906" w:h="16838" /><w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0" /><w:cols w:space="425" w:num="1" />
247  <w:textDirection w:val="tbRl" />
248</w:sectPr>"#
249        )
250    }
251
252    #[test]
253    fn test_section_property_default() {
254        let c = SectionProperty::new();
255        let b = c.build();
256        assert_eq!(
257            str::from_utf8(&b).unwrap(),
258            r#"<w:sectPr><w:pgSz w:w="11906" w:h="16838" /><w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0" /><w:cols w:space="425" w:num="1" />
259</w:sectPr>"#
260        );
261    }
262
263    #[test]
264    fn test_section_property_with_footer() {
265        let c = SectionProperty::new().footer(Footer::new(), "rId6");
266        let b = c.build();
267        assert_eq!(
268            str::from_utf8(&b).unwrap(),
269            r#"<w:sectPr><w:pgSz w:w="11906" w:h="16838" /><w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0" /><w:cols w:space="425" w:num="1" /><w:footerReference w:type="default" r:id="rId6" /></w:sectPr>"#
270        );
271    }
272
273    #[test]
274    fn test_section_property_with_title_pf() {
275        let c = SectionProperty::new().title_pg();
276        let b = c.build();
277        assert_eq!(
278            str::from_utf8(&b).unwrap(),
279            r#"<w:sectPr><w:pgSz w:w="11906" w:h="16838" /><w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0" /><w:cols w:space="425" w:num="1" />
280  <w:titlePg />
281</w:sectPr>"#
282        );
283    }
284}