docx_rs/documents/elements/
table_of_contents_item.rs1use serde::Serialize;
2use std::io::Write;
3
4use crate::documents::*;
5use crate::types::*;
6use crate::xml_builder::*;
7
8#[derive(Serialize, Debug, Clone, PartialEq, Default)]
9pub struct TableOfContentsItem {
10 pub instr: InstrToC,
11 pub text: String,
12 pub toc_key: String,
13 pub level: usize,
14 pub dirty: bool,
15 pub page_ref: Option<String>,
16}
17
18impl TableOfContentsItem {
19 pub fn new() -> Self {
20 Self {
21 level: 1,
22 ..Default::default()
23 }
24 }
25
26 pub fn instr(mut self, instr: InstrToC) -> Self {
27 self.instr = instr;
28 self
29 }
30
31 pub fn text(mut self, text: impl Into<String>) -> Self {
32 self.text = text.into();
33 self
34 }
35
36 pub fn level(mut self, level: usize) -> Self {
37 self.level = level;
38 self
39 }
40
41 pub fn toc_key(mut self, key: impl Into<String>) -> Self {
42 self.toc_key = key.into();
43 self
44 }
45
46 pub fn page_ref(mut self, r: impl Into<String>) -> Self {
47 self.page_ref = Some(r.into());
48 self
49 }
50}
51
52impl BuildXML for Vec<TableOfContentsItem> {
53 fn build_to<W: Write>(
54 &self,
55 stream: xml::writer::EventWriter<W>,
56 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
57 let mut b = XMLBuilder::from(stream)
58 .open_structured_tag()?
59 .open_structured_tag_property()?
60 .close()?
61 .open_structured_tag_content()?;
62
63 for (i, t) in self.iter().enumerate() {
64 let mut p = Paragraph::new().style(&format!("ToC{}", t.level));
65
66 if i == 0 {
67 p = p.unshift_run(
68 Run::new()
69 .add_field_char(FieldCharType::Begin, t.dirty)
70 .add_instr_text(InstrText::TOC(t.instr.clone()))
71 .add_field_char(FieldCharType::Separate, false),
72 );
73 }
74
75 {
76 p = p.add_tab(
77 Tab::new()
78 .val(TabValueType::Right)
79 .leader(TabLeaderType::Dot)
80 .pos(80000),
82 );
83
84 let run = Run::new().add_text(&t.text);
85 let page_ref = Run::new()
86 .add_field_char(FieldCharType::Begin, false)
87 .add_instr_text(InstrText::PAGEREF(
88 InstrPAGEREF::new(&t.toc_key).hyperlink(),
89 ))
90 .add_field_char(FieldCharType::Separate, false)
91 .add_text(t.page_ref.to_owned().unwrap_or_else(|| "1".to_string()))
92 .add_field_char(FieldCharType::End, false);
93
94 if t.instr.hyperlink {
95 p = p.add_hyperlink(
96 Hyperlink::new(&t.toc_key, HyperlinkType::Anchor)
97 .add_run(run)
98 .add_run(Run::new().add_tab())
99 .add_run(page_ref),
100 );
101 } else {
102 p = p
103 .add_run(run)
104 .add_run(Run::new().add_tab())
105 .add_run(page_ref);
106 }
107 b = b.add_child(&p)?;
108 }
109
110 if i == self.len() - 1 {
111 let mut p = Paragraph::new().style(&format!("ToC{}", t.level));
112 p = p.add_run(Run::new().add_field_char(FieldCharType::End, false));
113 b = b.add_child(&p)?;
114 }
115 }
116
117 b.close()?.close()?.into_inner()
118 }
119}