docx_rs/documents/elements/
table_of_contents_item.rs

1use 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                        // TODO: for now set 80000
81                        .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}