docx_rs/documents/elements/
style.rs

1use serde::Serialize;
2use std::io::Write;
3
4use crate::documents::BuildXML;
5use crate::escape::escape;
6use crate::types::*;
7use crate::xml_builder::*;
8use crate::StyleType;
9
10use super::*;
11
12#[derive(Debug, Clone, PartialEq, Serialize)]
13#[serde(rename_all = "camelCase")]
14pub struct Style {
15    pub style_id: String,
16    pub name: Name,
17    pub style_type: StyleType,
18    pub run_property: RunProperty,
19    pub paragraph_property: ParagraphProperty,
20    pub table_property: TableProperty,
21    pub table_cell_property: TableCellProperty,
22    pub based_on: Option<BasedOn>,
23    pub next: Option<Next>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub link: Option<Link>,
26}
27
28impl Default for Style {
29    fn default() -> Self {
30        let name = Name::new("");
31        let rpr = RunProperty::new();
32        let ppr = ParagraphProperty::new();
33        Style {
34            style_id: "".to_owned(),
35            style_type: StyleType::Paragraph,
36            name,
37            run_property: rpr,
38            paragraph_property: ppr,
39            table_property: TableProperty::new(),
40            table_cell_property: TableCellProperty::new(),
41            based_on: None,
42            next: None,
43            link: None,
44        }
45    }
46}
47
48impl Style {
49    pub fn new(style_id: impl Into<String>, style_type: StyleType) -> Self {
50        let default = Default::default();
51        Style {
52            style_id: escape(&style_id.into()),
53            style_type,
54            ..default
55        }
56    }
57
58    pub fn name(mut self, name: impl Into<String>) -> Self {
59        self.name = Name::new(name);
60        self
61    }
62
63    pub fn based_on(mut self, base: impl Into<String>) -> Self {
64        self.based_on = Some(BasedOn::new(base));
65        self
66    }
67
68    pub fn next(mut self, next: impl Into<String>) -> Self {
69        self.next = Some(Next::new(next));
70        self
71    }
72
73    pub fn link(mut self, link: impl Into<String>) -> Self {
74        self.link = Some(Link::new(link));
75        self
76    }
77
78    pub fn size(mut self, size: usize) -> Self {
79        self.run_property = self.run_property.size(size);
80        self
81    }
82
83    pub fn color(mut self, color: impl Into<String>) -> Self {
84        self.run_property = self.run_property.color(color);
85        self
86    }
87
88    pub fn highlight(mut self, color: impl Into<String>) -> Self {
89        self.run_property = self.run_property.highlight(color);
90        self
91    }
92
93    pub fn bold(mut self) -> Self {
94        self.run_property = self.run_property.bold();
95        self
96    }
97
98    pub fn italic(mut self) -> Self {
99        self.run_property = self.run_property.italic();
100        self
101    }
102
103    pub fn underline(mut self, line_type: impl Into<String>) -> Self {
104        self.run_property = self.run_property.underline(line_type);
105        self
106    }
107
108    pub fn vanish(mut self) -> Self {
109        self.run_property = self.run_property.vanish();
110        self
111    }
112
113    pub fn text_border(mut self, b: TextBorder) -> Self {
114        self.run_property = self.run_property.text_border(b);
115        self
116    }
117
118    pub fn fonts(mut self, f: RunFonts) -> Self {
119        self.run_property = self.run_property.fonts(f);
120        self
121    }
122
123    pub fn align(mut self, alignment_type: AlignmentType) -> Self {
124        self.paragraph_property = self.paragraph_property.align(alignment_type);
125        self
126    }
127
128    pub fn text_alignment(mut self, alignment_type: TextAlignmentType) -> Self {
129        self.paragraph_property = self.paragraph_property.text_alignment(alignment_type);
130        self
131    }
132
133    pub fn snap_to_grid(mut self, v: bool) -> Self {
134        self.paragraph_property = self.paragraph_property.snap_to_grid(v);
135        self
136    }
137
138    pub fn line_spacing(mut self, spacing: LineSpacing) -> Self {
139        self.paragraph_property = self.paragraph_property.line_spacing(spacing);
140        self
141    }
142
143    pub fn indent(
144        mut self,
145        left: Option<i32>,
146        special_indent: Option<SpecialIndentType>,
147        end: Option<i32>,
148        start_chars: Option<i32>,
149    ) -> Self {
150        self.paragraph_property =
151            self.paragraph_property
152                .indent(left, special_indent, end, start_chars);
153        self
154    }
155
156    pub fn hanging_chars(mut self, chars: i32) -> Self {
157        self.paragraph_property = self.paragraph_property.hanging_chars(chars);
158        self
159    }
160
161    pub fn first_line_chars(mut self, chars: i32) -> Self {
162        self.paragraph_property = self.paragraph_property.first_line_chars(chars);
163        self
164    }
165
166    pub fn outline_lvl(mut self, l: usize) -> Self {
167        self.paragraph_property = self.paragraph_property.outline_lvl(l);
168        self
169    }
170
171    pub fn table_property(mut self, p: TableProperty) -> Self {
172        self.table_property = p;
173        self
174    }
175
176    pub fn table_indent(mut self, v: i32) -> Self {
177        self.table_property = self.table_property.indent(v);
178        self
179    }
180
181    pub fn table_align(mut self, v: TableAlignmentType) -> Self {
182        self.table_property = self.table_property.align(v);
183        self
184    }
185
186    pub fn style(mut self, s: impl Into<String>) -> Self {
187        self.table_property = self.table_property.style(s);
188        self
189    }
190
191    pub fn layout(mut self, t: TableLayoutType) -> Self {
192        self.table_property = self.table_property.layout(t);
193        self
194    }
195
196    pub fn width(mut self, w: usize, t: WidthType) -> Self {
197        self.table_property = self.table_property.width(w, t);
198        self
199    }
200
201    pub fn margins(mut self, margins: TableCellMargins) -> Self {
202        self.table_property = self.table_property.set_margins(margins);
203        self
204    }
205
206    pub fn set_borders(mut self, borders: TableBorders) -> Self {
207        self.table_property = self.table_property.set_borders(borders);
208        self
209    }
210
211    pub fn set_border(mut self, border: TableBorder) -> Self {
212        self.table_property = self.table_property.set_border(border);
213        self
214    }
215
216    pub fn clear_border(mut self, position: TableBorderPosition) -> Self {
217        self.table_property = self.table_property.clear_border(position);
218        self
219    }
220
221    pub fn clear_all_border(mut self) -> Self {
222        self.table_property = self.table_property.clear_all_border();
223        self
224    }
225
226    pub fn table_cell_property(mut self, p: TableCellProperty) -> Self {
227        self.table_cell_property = p;
228        self
229    }
230
231    // frameProperty
232    pub fn wrap(mut self, wrap: impl Into<String>) -> Self {
233        self.paragraph_property.frame_property = Some(FrameProperty {
234            wrap: Some(wrap.into()),
235            ..self.paragraph_property.frame_property.unwrap_or_default()
236        });
237        self
238    }
239
240    pub fn v_anchor(mut self, anchor: impl Into<String>) -> Self {
241        self.paragraph_property.frame_property = Some(FrameProperty {
242            v_anchor: Some(anchor.into()),
243            ..self.paragraph_property.frame_property.unwrap_or_default()
244        });
245        self
246    }
247
248    pub fn h_anchor(mut self, anchor: impl Into<String>) -> Self {
249        self.paragraph_property.frame_property = Some(FrameProperty {
250            h_anchor: Some(anchor.into()),
251            ..self.paragraph_property.frame_property.unwrap_or_default()
252        });
253        self
254    }
255
256    pub fn h_rule(mut self, r: impl Into<String>) -> Self {
257        self.paragraph_property.frame_property = Some(FrameProperty {
258            h_rule: Some(r.into()),
259            ..self.paragraph_property.frame_property.unwrap_or_default()
260        });
261        self
262    }
263
264    pub fn x_align(mut self, align: impl Into<String>) -> Self {
265        self.paragraph_property.frame_property = Some(FrameProperty {
266            x_align: Some(align.into()),
267            ..self.paragraph_property.frame_property.unwrap_or_default()
268        });
269        self
270    }
271
272    pub fn y_align(mut self, align: impl Into<String>) -> Self {
273        self.paragraph_property.frame_property = Some(FrameProperty {
274            y_align: Some(align.into()),
275            ..self.paragraph_property.frame_property.unwrap_or_default()
276        });
277        self
278    }
279
280    pub fn h_space(mut self, x: i32) -> Self {
281        self.paragraph_property.frame_property = Some(FrameProperty {
282            h_space: Some(x),
283            ..self.paragraph_property.frame_property.unwrap_or_default()
284        });
285        self
286    }
287
288    pub fn v_space(mut self, x: i32) -> Self {
289        self.paragraph_property.frame_property = Some(FrameProperty {
290            v_space: Some(x),
291            ..self.paragraph_property.frame_property.unwrap_or_default()
292        });
293        self
294    }
295
296    pub fn frame_x(mut self, x: i32) -> Self {
297        self.paragraph_property.frame_property = Some(FrameProperty {
298            x: Some(x),
299            ..self.paragraph_property.frame_property.unwrap_or_default()
300        });
301        self
302    }
303
304    pub fn frame_y(mut self, y: i32) -> Self {
305        self.paragraph_property.frame_property = Some(FrameProperty {
306            y: Some(y),
307            ..self.paragraph_property.frame_property.unwrap_or_default()
308        });
309        self
310    }
311
312    pub fn frame_width(mut self, n: u32) -> Self {
313        self.paragraph_property.frame_property = Some(FrameProperty {
314            w: Some(n),
315            ..self.paragraph_property.frame_property.unwrap_or_default()
316        });
317        self
318    }
319
320    pub fn frame_height(mut self, n: u32) -> Self {
321        self.paragraph_property.frame_property = Some(FrameProperty {
322            h: Some(n),
323            ..self.paragraph_property.frame_property.unwrap_or_default()
324        });
325        self
326    }
327}
328
329impl BuildXML for Style {
330    fn build_to<W: Write>(
331        &self,
332        stream: xml::writer::EventWriter<W>,
333    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
334        // Set "Normal" as default if you need change these values please fix it
335        XMLBuilder::from(stream)
336            .open_style(self.style_type, &self.style_id)?
337            .add_child(&self.name)?
338            .add_child(&self.run_property)?
339            .add_child(&self.paragraph_property)?
340            .apply_if(self.style_type == StyleType::Table, |b| {
341                b.add_child(&self.table_cell_property)?
342                    .add_child(&self.table_property)
343            })?
344            .add_optional_child(&self.next)?
345            .add_optional_child(&self.link)?
346            .add_child(&QFormat::new())?
347            .add_optional_child(&self.based_on)?
348            .close()?
349            .into_inner()
350    }
351}
352
353#[cfg(test)]
354mod tests {
355
356    use super::*;
357    #[cfg(test)]
358    use pretty_assertions::assert_eq;
359    use std::str;
360
361    #[test]
362    fn test_build() {
363        let c = Style::new("Heading", StyleType::Paragraph).name("Heading1");
364        let b = c.build();
365        assert_eq!(
366            str::from_utf8(&b).unwrap(),
367            r#"<w:style w:type="paragraph" w:styleId="Heading"><w:name w:val="Heading1" /><w:rPr /><w:pPr><w:rPr /></w:pPr><w:qFormat /></w:style>"#
368        );
369    }
370}