docx_rs/documents/elements/
level.rs1use crate::documents::*;
2use crate::types::*;
3use crate::xml_builder::*;
4use std::io::Write;
5
6use serde::Serialize;
7
8#[derive(Debug, Clone, PartialEq, Serialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Level {
11 pub level: usize,
12 pub start: Start,
13 pub format: NumberFormat,
14 pub text: LevelText,
15 pub jc: LevelJc,
16 pub paragraph_property: ParagraphProperty,
17 pub run_property: RunProperty,
18 pub suffix: LevelSuffixType,
19 pub pstyle: Option<ParagraphStyle>,
20 pub level_restart: Option<LevelRestart>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub is_lgl: Option<IsLgl>,
23}
24
25impl Level {
26 pub fn new(
27 level: usize,
28 start: Start,
29 format: NumberFormat,
30 text: LevelText,
31 jc: LevelJc,
32 ) -> Level {
33 Self {
34 level,
35 start,
36 format,
37 text,
38 jc,
39 paragraph_property: ParagraphProperty::new(),
40 run_property: RunProperty::new(),
41 suffix: LevelSuffixType::Tab,
42 pstyle: None,
43 level_restart: None,
44 is_lgl: None,
45 }
46 }
47
48 pub fn indent(
49 mut self,
50 left: Option<i32>,
51 special_indent: Option<SpecialIndentType>,
52 end: Option<i32>,
53 start_chars: Option<i32>,
54 ) -> Self {
55 self.paragraph_property =
56 self.paragraph_property
57 .indent(left, special_indent, end, start_chars);
58 self
59 }
60
61 pub fn paragraph_style(mut self, style_id: impl Into<String>) -> Self {
62 self.pstyle = Some(ParagraphStyle::new(Some(style_id.into())));
63 self
64 }
65
66 pub fn suffix(mut self, s: LevelSuffixType) -> Self {
67 self.suffix = s;
68 self
69 }
70
71 pub fn size(mut self, size: usize) -> Self {
73 self.run_property = self.run_property.size(size);
74 self
75 }
76
77 pub fn spacing(mut self, v: i32) -> Self {
78 self.run_property = self.run_property.spacing(v);
79 self
80 }
81
82 pub fn color(mut self, color: impl Into<String>) -> Self {
83 self.run_property = self.run_property.color(color);
84 self
85 }
86
87 pub fn highlight(mut self, color: impl Into<String>) -> Self {
88 self.run_property = self.run_property.highlight(color);
89 self
90 }
91
92 pub fn bold(mut self) -> Self {
93 self.run_property = self.run_property.bold();
94 self
95 }
96
97 pub fn disable_bold(mut self) -> Self {
98 self.run_property = self.run_property.disable_bold();
99 self
100 }
101
102 pub fn italic(mut self) -> Self {
103 self.run_property = self.run_property.italic();
104 self
105 }
106
107 pub fn disable_italic(mut self) -> Self {
108 self.run_property = self.run_property.disable_italic();
109 self
110 }
111
112 pub fn strike(mut self) -> Self {
113 self.run_property = self.run_property.strike();
114 self
115 }
116
117 pub fn disable_strike(mut self) -> Self {
118 self.run_property = self.run_property.disable_strike();
119 self
120 }
121
122 pub fn dstrike(mut self) -> Self {
123 self.run_property = self.run_property.dstrike();
124 self
125 }
126
127 pub fn disable_dstrike(mut self) -> Self {
128 self.run_property = self.run_property.disable_dstrike();
129 self
130 }
131
132 pub fn underline(mut self, line_type: impl Into<String>) -> Self {
133 self.run_property = self.run_property.underline(line_type);
134 self
135 }
136
137 pub fn vanish(mut self) -> Self {
138 self.run_property = self.run_property.vanish();
139 self
140 }
141
142 pub fn fonts(mut self, f: RunFonts) -> Self {
143 self.run_property = self.run_property.fonts(f);
144 self
145 }
146
147 pub fn level_restart(mut self, v: u32) -> Self {
148 self.level_restart = Some(LevelRestart::new(v));
149 self
150 }
151
152 pub fn is_lgl(mut self) -> Self {
153 self.is_lgl = Some(IsLgl::new());
154 self
155 }
156}
157
158impl BuildXML for Level {
159 fn build_to<W: Write>(
160 &self,
161 stream: xml::writer::EventWriter<W>,
162 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
163 XMLBuilder::from(stream)
164 .open_level(&format!("{}", self.level))?
165 .add_child(&self.start)?
166 .add_child(&self.format)?
167 .add_child(&self.text)?
168 .add_child(&self.jc)?
169 .add_child(&self.paragraph_property)?
170 .add_child(&self.run_property)?
171 .add_optional_child(&self.pstyle)?
172 .add_optional_child(&self.level_restart)?
173 .add_optional_child(&self.is_lgl)?
174 .apply_if(self.suffix != LevelSuffixType::Tab, |b| {
175 b.suffix(&self.suffix.to_string())
176 })?
177 .close()?
178 .into_inner()
179 }
180}
181
182#[cfg(test)]
183mod tests {
184
185 use super::*;
186 #[cfg(test)]
187 use pretty_assertions::assert_eq;
188 use std::str;
189
190 #[test]
191 fn test_level() {
192 let b = Level::new(
193 1,
194 Start::new(1),
195 NumberFormat::new("decimal"),
196 LevelText::new("%4."),
197 LevelJc::new("left"),
198 )
199 .build();
200 assert_eq!(
201 str::from_utf8(&b).unwrap(),
202 r#"<w:lvl w:ilvl="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:rPr /></w:pPr><w:rPr /></w:lvl>"#
203 );
204 }
205
206 #[test]
207 fn test_level_indent() {
208 let b = Level::new(
209 1,
210 Start::new(1),
211 NumberFormat::new("decimal"),
212 LevelText::new("%4."),
213 LevelJc::new("left"),
214 )
215 .indent(Some(320), Some(SpecialIndentType::Hanging(200)), None, None)
216 .build();
217 assert_eq!(
218 str::from_utf8(&b).unwrap(),
219 r#"<w:lvl w:ilvl="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:rPr /><w:ind w:left="320" w:right="0" w:hanging="200" /></w:pPr><w:rPr /></w:lvl>"#
220 );
221 }
222 #[test]
223 fn test_level_with_suff() {
224 let b = Level::new(
225 1,
226 Start::new(1),
227 NumberFormat::new("decimal"),
228 LevelText::new("%4."),
229 LevelJc::new("left"),
230 )
231 .suffix(LevelSuffixType::Space)
232 .build();
233 assert_eq!(
234 str::from_utf8(&b).unwrap(),
235 r#"<w:lvl w:ilvl="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:rPr /></w:pPr><w:rPr /><w:suff w:val="space" /></w:lvl>"#
236 );
237 }
238 #[test]
239 fn test_level_with_pstyle() {
240 let b = Level::new(
241 1,
242 Start::new(1),
243 NumberFormat::new("decimal"),
244 LevelText::new("%4."),
245 LevelJc::new("left"),
246 )
247 .paragraph_style("a-style")
248 .build();
249 assert_eq!(
250 str::from_utf8(&b).unwrap(),
251 r#"<w:lvl w:ilvl="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:rPr /></w:pPr><w:rPr /><w:pStyle w:val="a-style" /></w:lvl>"#
252 );
253 }
254}