ppt_rs/generator/
slide_content.rs

1//! Slide content and layout types
2
3use super::tables::Table;
4use super::shapes::Shape;
5use super::images::Image;
6use super::connectors::Connector;
7use super::media::{Video, Audio};
8use super::charts::Chart;
9
10/// Slide layout types
11#[derive(Clone, Debug, Copy, PartialEq, Eq)]
12pub enum SlideLayout {
13    /// Title only (no content area)
14    TitleOnly,
15    /// Title and content (bullets)
16    TitleAndContent,
17    /// Title at top, content fills rest
18    TitleAndBigContent,
19    /// Blank slide
20    Blank,
21    /// Title centered on slide
22    CenteredTitle,
23    /// Two columns: title on left, content on right
24    TwoColumn,
25}
26
27impl SlideLayout {
28    pub fn as_str(&self) -> &'static str {
29        match self {
30            SlideLayout::TitleOnly => "titleOnly",
31            SlideLayout::TitleAndContent => "titleAndContent",
32            SlideLayout::TitleAndBigContent => "titleAndBigContent",
33            SlideLayout::Blank => "blank",
34            SlideLayout::CenteredTitle => "centeredTitle",
35            SlideLayout::TwoColumn => "twoColumn",
36        }
37    }
38}
39
40/// Slide content for more complex presentations
41#[derive(Clone, Debug)]
42pub struct SlideContent {
43    pub title: String,
44    pub content: Vec<String>,
45    pub title_size: Option<u32>,
46    pub content_size: Option<u32>,
47    pub title_bold: bool,
48    pub content_bold: bool,
49    pub title_italic: bool,
50    pub content_italic: bool,
51    pub title_underline: bool,
52    pub content_underline: bool,
53    pub title_color: Option<String>,
54    pub content_color: Option<String>,
55    pub has_table: bool,
56    pub has_chart: bool,
57    pub has_image: bool,
58    pub layout: SlideLayout,
59    pub table: Option<Table>,
60    pub shapes: Vec<Shape>,
61    pub images: Vec<Image>,
62    /// Speaker notes for the slide
63    pub notes: Option<String>,
64    /// Connectors between shapes
65    pub connectors: Vec<Connector>,
66    /// Videos embedded in slide
67    pub videos: Vec<Video>,
68    /// Audio files embedded in slide
69    pub audios: Vec<Audio>,
70    /// Charts embedded in slide
71    pub charts: Vec<Chart>,
72}
73
74impl SlideContent {
75    pub fn new(title: &str) -> Self {
76        SlideContent {
77            title: title.to_string(),
78            content: Vec::new(),
79            title_size: Some(44),
80            content_size: Some(28),
81            title_bold: true,
82            content_bold: false,
83            title_italic: false,
84            content_italic: false,
85            title_underline: false,
86            content_underline: false,
87            title_color: None,
88            content_color: None,
89            has_table: false,
90            has_chart: false,
91            has_image: false,
92            layout: SlideLayout::TitleAndContent,
93            table: None,
94            shapes: Vec::new(),
95            images: Vec::new(),
96            notes: None,
97            connectors: Vec::new(),
98            videos: Vec::new(),
99            audios: Vec::new(),
100            charts: Vec::new(),
101        }
102    }
103
104    pub fn add_bullet(mut self, text: &str) -> Self {
105        self.content.push(text.to_string());
106        self
107    }
108
109    pub fn title_size(mut self, size: u32) -> Self {
110        self.title_size = Some(size);
111        self
112    }
113
114    pub fn content_size(mut self, size: u32) -> Self {
115        self.content_size = Some(size);
116        self
117    }
118
119    pub fn title_bold(mut self, bold: bool) -> Self {
120        self.title_bold = bold;
121        self
122    }
123
124    pub fn content_bold(mut self, bold: bool) -> Self {
125        self.content_bold = bold;
126        self
127    }
128
129    pub fn title_italic(mut self, italic: bool) -> Self {
130        self.title_italic = italic;
131        self
132    }
133
134    pub fn content_italic(mut self, italic: bool) -> Self {
135        self.content_italic = italic;
136        self
137    }
138
139    pub fn title_underline(mut self, underline: bool) -> Self {
140        self.title_underline = underline;
141        self
142    }
143
144    pub fn content_underline(mut self, underline: bool) -> Self {
145        self.content_underline = underline;
146        self
147    }
148
149    pub fn title_color(mut self, color: &str) -> Self {
150        self.title_color = Some(color.trim_start_matches('#').to_uppercase());
151        self
152    }
153
154    pub fn content_color(mut self, color: &str) -> Self {
155        self.content_color = Some(color.trim_start_matches('#').to_uppercase());
156        self
157    }
158
159    pub fn with_table(mut self) -> Self {
160        self.has_table = true;
161        self
162    }
163
164    pub fn with_chart(mut self) -> Self {
165        self.has_chart = true;
166        self
167    }
168
169    pub fn with_image(mut self) -> Self {
170        self.has_image = true;
171        self
172    }
173
174    pub fn layout(mut self, layout: SlideLayout) -> Self {
175        self.layout = layout;
176        self
177    }
178
179    pub fn table(mut self, table: Table) -> Self {
180        self.table = Some(table);
181        self.has_table = true;
182        self
183    }
184
185    /// Add a shape to the slide
186    pub fn add_shape(mut self, shape: Shape) -> Self {
187        self.shapes.push(shape);
188        self
189    }
190
191    /// Add multiple shapes to the slide
192    pub fn with_shapes(mut self, shapes: Vec<Shape>) -> Self {
193        self.shapes.extend(shapes);
194        self
195    }
196
197    /// Add an image to the slide
198    pub fn add_image(mut self, image: Image) -> Self {
199        self.images.push(image);
200        self.has_image = true;
201        self
202    }
203
204    /// Add multiple images to the slide
205    pub fn with_images(mut self, images: Vec<Image>) -> Self {
206        self.images.extend(images);
207        self.has_image = true;
208        self
209    }
210
211    /// Add speaker notes to the slide
212    pub fn notes(mut self, notes: &str) -> Self {
213        self.notes = Some(notes.to_string());
214        self
215    }
216
217    /// Check if slide has speaker notes
218    pub fn has_notes(&self) -> bool {
219        self.notes.is_some()
220    }
221
222    /// Add a connector to the slide
223    pub fn add_connector(mut self, connector: Connector) -> Self {
224        self.connectors.push(connector);
225        self
226    }
227
228    /// Add multiple connectors to the slide
229    pub fn with_connectors(mut self, connectors: Vec<Connector>) -> Self {
230        self.connectors.extend(connectors);
231        self
232    }
233
234    /// Add a video to the slide
235    pub fn add_video(mut self, video: Video) -> Self {
236        self.videos.push(video);
237        self
238    }
239
240    /// Add multiple videos to the slide
241    pub fn with_videos(mut self, videos: Vec<Video>) -> Self {
242        self.videos.extend(videos);
243        self
244    }
245
246    /// Add an audio file to the slide
247    pub fn add_audio(mut self, audio: Audio) -> Self {
248        self.audios.push(audio);
249        self
250    }
251
252    /// Add multiple audio files to the slide
253    pub fn with_audios(mut self, audios: Vec<Audio>) -> Self {
254        self.audios.extend(audios);
255        self
256    }
257
258    /// Add a chart to the slide
259    pub fn add_chart(mut self, chart: Chart) -> Self {
260        self.charts.push(chart);
261        self.has_chart = true;
262        self
263    }
264
265    /// Add multiple charts to the slide
266    pub fn with_charts(mut self, charts: Vec<Chart>) -> Self {
267        self.charts.extend(charts);
268        self.has_chart = true;
269        self
270    }
271
272    /// Check if slide has any media
273    pub fn has_media(&self) -> bool {
274        !self.videos.is_empty() || !self.audios.is_empty()
275    }
276
277    /// Check if slide has connectors
278    pub fn has_connectors(&self) -> bool {
279        !self.connectors.is_empty()
280    }
281}