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