ppt_rs/parts/
slide_master.rs1use super::base::{ContentType, Part, PartType};
6use crate::exc::PptxError;
7
8#[derive(Debug, Clone)]
10pub struct SlideMasterPart {
11 path: String,
12 master_number: usize,
13 name: String,
14 theme_rel_id: String,
15 layout_rel_ids: Vec<String>,
16 xml_content: Option<String>,
17}
18
19impl SlideMasterPart {
20 pub fn new(master_number: usize) -> Self {
22 SlideMasterPart {
23 path: format!("ppt/slideMasters/slideMaster{}.xml", master_number),
24 master_number,
25 name: "Office Theme".to_string(),
26 theme_rel_id: "rId1".to_string(),
27 layout_rel_ids: vec![],
28 xml_content: None,
29 }
30 }
31
32 pub fn master_number(&self) -> usize {
34 self.master_number
35 }
36
37 pub fn name(&self) -> &str {
39 &self.name
40 }
41
42 pub fn set_name(&mut self, name: impl Into<String>) {
44 self.name = name.into();
45 }
46
47 pub fn add_layout_rel_id(&mut self, rel_id: impl Into<String>) {
49 self.layout_rel_ids.push(rel_id.into());
50 }
51
52 pub fn layout_rel_ids(&self) -> &[String] {
54 &self.layout_rel_ids
55 }
56
57 pub fn set_theme_rel_id(&mut self, rel_id: impl Into<String>) {
59 self.theme_rel_id = rel_id.into();
60 }
61
62 pub fn rel_target(&self) -> String {
64 format!("slideMasters/slideMaster{}.xml", self.master_number)
65 }
66
67 fn generate_xml(&self) -> String {
68 let layout_ids: String = self
69 .layout_rel_ids
70 .iter()
71 .map(|id| {
72 format!(
73 r#"<p:sldLayoutId id="{}" r:id="{}"/>"#,
74 2147483649 + self.layout_rel_ids.iter().position(|x| x == id).unwrap() as u64,
75 id
76 )
77 })
78 .collect::<Vec<_>>()
79 .join("\n ");
80
81 format!(
82 r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
83<p:sldMaster xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
84 <p:cSld>
85 <p:bg>
86 <p:bgRef idx="1001">
87 <a:schemeClr val="bg1"/>
88 </p:bgRef>
89 </p:bg>
90 <p:spTree>
91 <p:nvGrpSpPr>
92 <p:cNvPr id="1" name=""/>
93 <p:cNvGrpSpPr/>
94 <p:nvPr/>
95 </p:nvGrpSpPr>
96 <p:grpSpPr>
97 <a:xfrm>
98 <a:off x="0" y="0"/>
99 <a:ext cx="0" cy="0"/>
100 <a:chOff x="0" y="0"/>
101 <a:chExt cx="0" cy="0"/>
102 </a:xfrm>
103 </p:grpSpPr>
104 </p:spTree>
105 </p:cSld>
106 <p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>
107 <p:sldLayoutIdLst>
108 {}</p:sldLayoutIdLst>
109 <p:txStyles>
110 <p:titleStyle/>
111 <p:bodyStyle/>
112 <p:otherStyle/>
113 </p:txStyles>
114</p:sldMaster>"#,
115 if layout_ids.is_empty() {
116 "".to_string()
117 } else {
118 format!("\n {}\n ", layout_ids)
119 }
120 )
121 }
122}
123
124impl Part for SlideMasterPart {
125 fn path(&self) -> &str {
126 &self.path
127 }
128
129 fn part_type(&self) -> PartType {
130 PartType::SlideMaster
131 }
132
133 fn content_type(&self) -> ContentType {
134 ContentType::SlideMaster
135 }
136
137 fn to_xml(&self) -> Result<String, PptxError> {
138 if let Some(ref xml) = self.xml_content {
139 return Ok(xml.clone());
140 }
141 Ok(self.generate_xml())
142 }
143
144 fn from_xml(xml: &str) -> Result<Self, PptxError> {
145 Ok(SlideMasterPart {
146 path: "ppt/slideMasters/slideMaster1.xml".to_string(),
147 master_number: 1,
148 name: "Office Theme".to_string(),
149 theme_rel_id: "rId1".to_string(),
150 layout_rel_ids: vec![],
151 xml_content: Some(xml.to_string()),
152 })
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_slide_master_new() {
162 let master = SlideMasterPart::new(1);
163 assert_eq!(master.master_number(), 1);
164 assert_eq!(master.path(), "ppt/slideMasters/slideMaster1.xml");
165 }
166
167 #[test]
168 fn test_slide_master_name() {
169 let mut master = SlideMasterPart::new(1);
170 assert_eq!(master.name(), "Office Theme");
171 master.set_name("Custom Theme");
172 assert_eq!(master.name(), "Custom Theme");
173 }
174
175 #[test]
176 fn test_slide_master_layouts() {
177 let mut master = SlideMasterPart::new(1);
178 master.add_layout_rel_id("rId2");
179 master.add_layout_rel_id("rId3");
180 assert_eq!(master.layout_rel_ids().len(), 2);
181 }
182
183 #[test]
184 fn test_slide_master_to_xml() {
185 let master = SlideMasterPart::new(1);
186 let xml = master.to_xml().unwrap();
187 assert!(xml.contains("p:sldMaster"));
188 assert!(xml.contains("p:clrMap"));
189 }
190
191 #[test]
192 fn test_slide_master_rel_target() {
193 let master = SlideMasterPart::new(2);
194 assert_eq!(master.rel_target(), "slideMasters/slideMaster2.xml");
195 }
196}