docx_reader/documents/elements/
paragraph_property.rs

1use serde::Serialize;
2
3use super::*;
4use crate::types::{AlignmentType, SpecialIndentType};
5use crate::ParagraphBorderPosition;
6
7#[derive(Serialize, Debug, Clone, PartialEq, Default)]
8#[serde(rename_all = "camelCase")]
9pub struct ParagraphProperty {
10	pub run_property: RunProperty,
11	#[serde(skip_serializing_if = "Option::is_none")]
12	pub style: Option<ParagraphStyle>,
13	#[serde(skip_serializing_if = "Option::is_none")]
14	pub numbering_property: Option<NumberingProperty>,
15	#[serde(skip_serializing_if = "Option::is_none")]
16	pub alignment: Option<Justification>,
17	#[serde(skip_serializing_if = "Option::is_none")]
18	pub indent: Option<Indent>,
19	#[serde(skip_serializing_if = "Option::is_none")]
20	pub line_spacing: Option<LineSpacing>,
21	#[serde(skip_serializing_if = "Option::is_none")]
22	pub keep_next: Option<bool>,
23	#[serde(skip_serializing_if = "Option::is_none")]
24	pub keep_lines: Option<bool>,
25	#[serde(skip_serializing_if = "Option::is_none")]
26	pub page_break_before: Option<bool>,
27	#[serde(skip_serializing_if = "Option::is_none")]
28	pub widow_control: Option<bool>,
29	#[serde(skip_serializing_if = "Option::is_none")]
30	pub outline_lvl: Option<OutlineLvl>,
31	#[serde(skip_serializing_if = "Option::is_none")]
32	pub section_property: Option<SectionProperty>,
33	pub tabs: Vec<Tab>,
34	// read only
35	#[serde(skip_serializing_if = "Option::is_none")]
36	pub(crate) div_id: Option<String>,
37	#[serde(skip_serializing_if = "Option::is_none")]
38	pub paragraph_property_change: Option<ParagraphPropertyChange>,
39	#[serde(skip_serializing_if = "Option::is_none")]
40	pub borders: Option<ParagraphBorders>,
41}
42
43// 17.3.1.26
44// pPr (Paragraph Properties)
45// This element specifies a set of paragraph properties which shall be applied to the contents of the parent
46// paragraph after all style/numbering/table properties have been applied to the text. These properties are defined
47// as direct formatting, since they are directly applied to the paragraph and supersede any formatting from styles.
48impl ParagraphProperty {
49	pub fn new() -> ParagraphProperty {
50		Default::default()
51	}
52
53	pub fn align(mut self, alignment_type: AlignmentType) -> Self {
54		self.alignment = Some(Justification::new(alignment_type.to_string()));
55		self
56	}
57
58	pub fn style(mut self, style_id: &str) -> Self {
59		self.style = Some(ParagraphStyle::new(Some(style_id)));
60		self
61	}
62
63	pub fn indent(
64		mut self,
65		left: Option<i32>,
66		special_indent: Option<SpecialIndentType>,
67		end: Option<i32>,
68		start_chars: Option<i32>,
69	) -> Self {
70		self.indent = Some(Indent::new(left, special_indent, end, start_chars));
71		self
72	}
73
74	pub fn numbering(mut self, id: NumberingId, level: IndentLevel) -> Self {
75		self.numbering_property = Some(NumberingProperty::new().add_num(id, level));
76		self
77	}
78
79	pub fn numbering_property(mut self, np: NumberingProperty) -> Self {
80		self.numbering_property = Some(np);
81		self
82	}
83
84	pub fn line_spacing(mut self, spacing: LineSpacing) -> Self {
85		self.line_spacing = Some(spacing);
86		self
87	}
88
89	pub fn character_spacing(mut self, spacing: i32) -> Self {
90		self.run_property.character_spacing = Some(CharacterSpacing::new(spacing));
91		self
92	}
93
94	pub fn keep_next(mut self, v: bool) -> Self {
95		self.keep_next = Some(v);
96		self
97	}
98
99	pub fn keep_lines(mut self, v: bool) -> Self {
100		self.keep_lines = Some(v);
101		self
102	}
103
104	pub fn outline_lvl(mut self, v: usize) -> Self {
105		if v >= 10 {
106			// clamped
107			self.outline_lvl = Some(OutlineLvl::new(9));
108			return self;
109		}
110		self.outline_lvl = Some(OutlineLvl::new(v));
111		self
112	}
113
114	pub fn page_break_before(mut self, v: bool) -> Self {
115		self.page_break_before = Some(v);
116		self
117	}
118
119	pub fn widow_control(mut self, v: bool) -> Self {
120		self.widow_control = Some(v);
121		self
122	}
123
124	pub fn add_tab(mut self, t: Tab) -> Self {
125		self.tabs.push(t);
126		self
127	}
128
129	pub fn section_property(mut self, s: SectionProperty) -> Self {
130		self.section_property = Some(s);
131		self
132	}
133
134	pub fn paragraph_property_change(mut self, p: ParagraphPropertyChange) -> Self {
135		self.paragraph_property_change = Some(p);
136		self
137	}
138
139	pub(crate) fn hanging_chars(mut self, chars: i32) -> Self {
140		if let Some(indent) = self.indent {
141			self.indent = Some(indent.hanging_chars(chars));
142		}
143		self
144	}
145
146	pub(crate) fn first_line_chars(mut self, chars: i32) -> Self {
147		if let Some(indent) = self.indent {
148			self.indent = Some(indent.first_line_chars(chars));
149		}
150		self
151	}
152
153	pub fn set_borders(mut self, borders: ParagraphBorders) -> Self {
154		self.borders = Some(borders);
155		self
156	}
157
158	pub fn set_border(mut self, border: ParagraphBorder) -> Self {
159		self.borders = Some(self.borders.unwrap_or_default().set(border));
160		self
161	}
162
163	pub fn clear_border(mut self, position: ParagraphBorderPosition) -> Self {
164		self.borders = Some(self.borders.unwrap_or_default().clear(position));
165		self
166	}
167
168	pub fn clear_all_borders(mut self) -> Self {
169		self.borders = Some(self.borders.unwrap_or_default().clear_all());
170		self
171	}
172}