pptx_rs/oxml/
presentation.rs1use std::str::FromStr;
33
34use crate::oxml::ns::{NS_DRAWING_MAIN, NS_PRESENTATION_MAIN};
35use crate::oxml::writer::XmlWriter;
36use crate::units::Emu;
37
38#[derive(Clone, Debug)]
40pub struct PresentationRoot {
41 pub slide_width: Option<Emu>,
43 pub slide_height: Option<Emu>,
45 pub slide_ids: Vec<SlideIdEntry>,
47 pub sld_master_ids: Vec<SldMasterIdEntry>,
52 pub default_text_style: Option<String>,
54 pub notes_size: Option<(Emu, Emu)>,
56 pub sections: crate::oxml::section::SectionList,
61}
62
63impl Default for PresentationRoot {
64 fn default() -> Self {
65 Self {
68 slide_width: None,
69 slide_height: None,
70 slide_ids: Vec::new(),
71 sld_master_ids: Vec::new(),
72 default_text_style: Some(DEFAULT_TEXT_STYLE.to_string()),
73 notes_size: None,
74 sections: crate::oxml::section::SectionList::default(),
75 }
76 }
77}
78
79#[derive(Clone, Debug)]
81pub struct SlideIdEntry {
82 pub id: u32,
84 pub rid: String,
86}
87
88#[derive(Clone, Debug)]
92pub struct SldMasterIdEntry {
93 pub id: u32,
95 pub rid: String,
97}
98
99impl PresentationRoot {
100 pub fn to_xml(&self) -> String {
102 let mut w = XmlWriter::with_decl();
103 let root_attrs: Vec<(&str, &str)> = vec![
104 ("xmlns:a", NS_DRAWING_MAIN),
105 ("xmlns:p", NS_PRESENTATION_MAIN),
106 ("xmlns:r", crate::oxml::ns::NS_DRAWING_RELS),
107 (
108 "xmlns:p14",
109 "http://schemas.microsoft.com/office/powerpoint/2010/main",
110 ),
111 ];
112 w.open_with("p:presentation", &root_attrs);
113
114 w.open("p:sldMasterIdLst");
116 if self.sld_master_ids.is_empty() {
117 w.empty_with("p:sldMasterId", &[("id", "2147483648"), ("r:id", "rIdP1")]);
119 } else {
120 for m in &self.sld_master_ids {
122 let id_s = m.id.to_string();
123 w.empty_with("p:sldMasterId", &[("id", &id_s), ("r:id", m.rid.as_str())]);
124 }
125 }
126 w.close("p:sldMasterIdLst");
127
128 w.open("p:sldIdLst");
130 for s in &self.slide_ids {
131 let id_s = s.id.to_string();
133 w.empty_with("p:sldId", &[("id", &id_s), ("r:id", s.rid.as_str())]);
134 }
135 w.close("p:sldIdLst");
136
137 if let (Some(w_), Some(h)) = (self.slide_width, self.slide_height) {
139 let cx_s = w_.value().to_string();
140 let cy_s = h.value().to_string();
141 w.empty_with("p:sldSz", &[("cx", &cx_s), ("cy", &cy_s)]);
142 }
143 let (nw, nh) = self.notes_size.unwrap_or((Emu(6_858_000), Emu(9_144_000)));
145 let ncx = nw.value().to_string();
146 let ncy = nh.value().to_string();
147 w.empty_with("p:notesSz", &[("cx", &ncx), ("cy", &ncy)]);
148 if let Some(s) = &self.default_text_style {
150 w.raw(s);
151 }
152 let section_xml = self.sections.write_xml();
156 if !section_xml.is_empty() {
157 w.raw(§ion_xml);
158 }
159
160 w.close("p:presentation");
161 w.into_string()
162 }
163}
164
165impl FromStr for PresentationRoot {
166 type Err = crate::Error;
167 fn from_str(_s: &str) -> Result<Self, Self::Err> {
168 Ok(PresentationRoot::default())
170 }
171}
172
173const DEFAULT_TEXT_STYLE: &str = r##"<p:defaultTextStyle><a:defPPr><a:defRPr lang="en-US"/></a:defPPr><a:lvl1pPr marL="0" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl1pPr><a:lvl2pPr marL="457200" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl2pPr><a:lvl3pPr marL="914400" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl3pPr><a:lvl4pPr marL="1371600" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl4pPr><a:lvl5pPr marL="1828800" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl5pPr><a:lvl6pPr marL="2286000" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl6pPr><a:lvl7pPr marL="2743200" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl7pPr><a:lvl8pPr marL="3200400" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl8pPr><a:lvl9pPr marL="3657600" algn="l" defTabSz="457200" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill><a:latin typeface="+mn-lt"/><a:ea typeface="+mn-ea"/><a:cs typeface="+mn-cs"/></a:defRPr></a:lvl9pPr></p:defaultTextStyle>"##;