dais_ui/presenter/
notes_panel.rs1use dais_core::bus::CommandSender;
6use dais_core::commands::Command;
7
8pub struct NotesPanelView<'a> {
9 pub notes: Option<&'a str>,
10 pub font_size: f32,
11 pub visible: bool,
12 pub editing: bool,
13}
14
15pub struct NotesPanel {
17 cache: egui_commonmark::CommonMarkCache,
18}
19
20impl NotesPanel {
21 pub fn new() -> Self {
22 Self { cache: egui_commonmark::CommonMarkCache::default() }
23 }
24
25 pub fn show(
27 &mut self,
28 ui: &mut egui::Ui,
29 area: egui::Rect,
30 view: &NotesPanelView<'_>,
31 sender: &CommandSender,
32 ) {
33 if !view.visible {
34 return;
35 }
36
37 let mut child_ui = ui.new_child(egui::UiBuilder::new().max_rect(area));
38
39 child_ui.scope_builder(
40 egui::UiBuilder::new()
41 .max_rect(egui::Rect::from_min_size(area.min, egui::vec2(area.width(), 20.0))),
42 |ui| {
43 ui.colored_label(egui::Color32::GRAY, "Notes");
44 },
45 );
46
47 let content_area = egui::Rect::from_min_size(
48 area.min + egui::vec2(8.0, 24.0),
49 egui::vec2((area.width() - 16.0).max(1.0), (area.height() - 28.0).max(1.0)),
50 );
51
52 child_ui.scope_builder(egui::UiBuilder::new().max_rect(content_area), |ui| {
53 ui.style_mut().override_font_id = Some(egui::FontId::proportional(view.font_size));
54
55 if view.editing {
56 ui.visuals_mut().extreme_bg_color = egui::Color32::from_gray(45);
58 ui.visuals_mut().override_text_color = Some(egui::Color32::WHITE);
59 ui.visuals_mut().widgets.active.fg_stroke.color = egui::Color32::WHITE;
60 let mut buffer = view.notes.unwrap_or_default().to_string();
61 let edit = egui::TextEdit::multiline(&mut buffer)
62 .desired_width(f32::INFINITY)
63 .desired_rows(12)
64 .hint_text("Write speaker notes in Markdown");
65 let response = ui.add_sized(content_area.size(), edit);
66 if response.changed() {
67 let _ = sender.send(Command::SetCurrentSlideNotes(buffer));
68 }
69 } else {
70 ui.visuals_mut().override_text_color = Some(egui::Color32::WHITE);
71 ui.visuals_mut().widgets.active.fg_stroke.color = egui::Color32::WHITE;
72 egui::ScrollArea::vertical().max_height(content_area.height()).show(ui, |ui| {
73 if let Some(text) = view.notes {
74 egui_commonmark::CommonMarkViewer::new().show(ui, &mut self.cache, text);
75 } else {
76 ui.colored_label(egui::Color32::from_gray(80), "No notes for this slide");
77 }
78 });
79 }
80 });
81 }
82}
83
84impl Default for NotesPanel {
85 fn default() -> Self {
86 Self::new()
87 }
88}