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