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/// A code block with syntax highlighting info
41#[derive(Clone, Debug)]
42pub struct CodeBlock {
43    pub code: String,
44    pub language: String,
45    pub x: i64,
46    pub y: i64,
47    pub width: i64,
48    pub height: i64,
49}
50
51impl CodeBlock {
52    pub fn new(code: &str, language: &str) -> Self {
53        Self {
54            code: code.to_string(),
55            language: language.to_string(),
56            x: 500000,
57            y: 1800000,
58            width: 8000000,
59            height: 4000000,
60        }
61    }
62    
63    pub fn position(mut self, x: i64, y: i64) -> Self {
64        self.x = x;
65        self.y = y;
66        self
67    }
68    
69    pub fn size(mut self, width: i64, height: i64) -> Self {
70        self.width = width;
71        self.height = height;
72        self
73    }
74}
75
76/// Slide content for more complex presentations
77#[derive(Clone, Debug)]
78pub struct SlideContent {
79    pub title: String,
80    pub content: Vec<String>,
81    pub title_size: Option<u32>,
82    pub content_size: Option<u32>,
83    pub title_bold: bool,
84    pub content_bold: bool,
85    pub title_italic: bool,
86    pub content_italic: bool,
87    pub title_underline: bool,
88    pub content_underline: bool,
89    pub title_color: Option<String>,
90    pub content_color: Option<String>,
91    pub has_table: bool,
92    pub has_chart: bool,
93    pub has_image: bool,
94    pub layout: SlideLayout,
95    pub table: Option<Table>,
96    pub shapes: Vec<Shape>,
97    pub images: Vec<Image>,
98    /// Speaker notes for the slide
99    pub notes: Option<String>,
100    /// Connectors between shapes
101    pub connectors: Vec<Connector>,
102    /// Videos embedded in slide
103    pub videos: Vec<Video>,
104    /// Audio files embedded in slide
105    pub audios: Vec<Audio>,
106    /// Charts embedded in slide
107    pub charts: Vec<Chart>,
108    /// Code blocks with syntax highlighting
109    pub code_blocks: Vec<CodeBlock>,
110}
111
112impl SlideContent {
113    pub fn new(title: &str) -> Self {
114        SlideContent {
115            title: title.to_string(),
116            content: Vec::new(),
117            title_size: Some(44),
118            content_size: Some(28),
119            title_bold: true,
120            content_bold: false,
121            title_italic: false,
122            content_italic: false,
123            title_underline: false,
124            content_underline: false,
125            title_color: None,
126            content_color: None,
127            has_table: false,
128            has_chart: false,
129            has_image: false,
130            layout: SlideLayout::TitleAndContent,
131            table: None,
132            shapes: Vec::new(),
133            images: Vec::new(),
134            notes: None,
135            connectors: Vec::new(),
136            videos: Vec::new(),
137            audios: Vec::new(),
138            charts: Vec::new(),
139            code_blocks: Vec::new(),
140        }
141    }
142
143    pub fn add_bullet(mut self, text: &str) -> Self {
144        self.content.push(text.to_string());
145        self
146    }
147
148    pub fn title_size(mut self, size: u32) -> Self {
149        self.title_size = Some(size);
150        self
151    }
152
153    pub fn content_size(mut self, size: u32) -> Self {
154        self.content_size = Some(size);
155        self
156    }
157
158    pub fn title_bold(mut self, bold: bool) -> Self {
159        self.title_bold = bold;
160        self
161    }
162
163    pub fn content_bold(mut self, bold: bool) -> Self {
164        self.content_bold = bold;
165        self
166    }
167
168    pub fn title_italic(mut self, italic: bool) -> Self {
169        self.title_italic = italic;
170        self
171    }
172
173    pub fn content_italic(mut self, italic: bool) -> Self {
174        self.content_italic = italic;
175        self
176    }
177
178    pub fn title_underline(mut self, underline: bool) -> Self {
179        self.title_underline = underline;
180        self
181    }
182
183    pub fn content_underline(mut self, underline: bool) -> Self {
184        self.content_underline = underline;
185        self
186    }
187
188    pub fn title_color(mut self, color: &str) -> Self {
189        self.title_color = Some(color.trim_start_matches('#').to_uppercase());
190        self
191    }
192
193    pub fn content_color(mut self, color: &str) -> Self {
194        self.content_color = Some(color.trim_start_matches('#').to_uppercase());
195        self
196    }
197
198    pub fn with_table(mut self) -> Self {
199        self.has_table = true;
200        self
201    }
202
203    pub fn with_chart(mut self) -> Self {
204        self.has_chart = true;
205        self
206    }
207
208    pub fn with_image(mut self) -> Self {
209        self.has_image = true;
210        self
211    }
212
213    pub fn layout(mut self, layout: SlideLayout) -> Self {
214        self.layout = layout;
215        self
216    }
217
218    pub fn table(mut self, table: Table) -> Self {
219        self.table = Some(table);
220        self.has_table = true;
221        self
222    }
223
224    /// Add a shape to the slide
225    pub fn add_shape(mut self, shape: Shape) -> Self {
226        self.shapes.push(shape);
227        self
228    }
229
230    /// Add multiple shapes to the slide
231    pub fn with_shapes(mut self, shapes: Vec<Shape>) -> Self {
232        self.shapes.extend(shapes);
233        self
234    }
235
236    /// Add an image to the slide
237    pub fn add_image(mut self, image: Image) -> Self {
238        self.images.push(image);
239        self.has_image = true;
240        self
241    }
242
243    /// Add multiple images to the slide
244    pub fn with_images(mut self, images: Vec<Image>) -> Self {
245        self.images.extend(images);
246        self.has_image = true;
247        self
248    }
249
250    /// Add speaker notes to the slide
251    pub fn notes(mut self, notes: &str) -> Self {
252        self.notes = Some(notes.to_string());
253        self
254    }
255
256    /// Check if slide has speaker notes
257    pub fn has_notes(&self) -> bool {
258        self.notes.is_some()
259    }
260
261    /// Add a connector to the slide
262    pub fn add_connector(mut self, connector: Connector) -> Self {
263        self.connectors.push(connector);
264        self
265    }
266
267    /// Add multiple connectors to the slide
268    pub fn with_connectors(mut self, connectors: Vec<Connector>) -> Self {
269        self.connectors.extend(connectors);
270        self
271    }
272
273    /// Add a video to the slide
274    pub fn add_video(mut self, video: Video) -> Self {
275        self.videos.push(video);
276        self
277    }
278
279    /// Add multiple videos to the slide
280    pub fn with_videos(mut self, videos: Vec<Video>) -> Self {
281        self.videos.extend(videos);
282        self
283    }
284
285    /// Add an audio file to the slide
286    pub fn add_audio(mut self, audio: Audio) -> Self {
287        self.audios.push(audio);
288        self
289    }
290
291    /// Add multiple audio files to the slide
292    pub fn with_audios(mut self, audios: Vec<Audio>) -> Self {
293        self.audios.extend(audios);
294        self
295    }
296
297    /// Add a chart to the slide
298    pub fn add_chart(mut self, chart: Chart) -> Self {
299        self.charts.push(chart);
300        self.has_chart = true;
301        self
302    }
303
304    /// Add multiple charts to the slide
305    pub fn with_charts(mut self, charts: Vec<Chart>) -> Self {
306        self.charts.extend(charts);
307        self.has_chart = true;
308        self
309    }
310
311    /// Check if slide has any media
312    pub fn has_media(&self) -> bool {
313        !self.videos.is_empty() || !self.audios.is_empty()
314    }
315
316    /// Check if slide has connectors
317    pub fn has_connectors(&self) -> bool {
318        !self.connectors.is_empty()
319    }
320}