docx_rs/documents/elements/
section_property.rs1use 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 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 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}