From aaf6c1c38aa6c59beda8110bd014cc6c96c6ec74 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Sun, 25 Oct 2026 21:13:50 -0400 Subject: [PATCH] refactor(show): split the key handler into grid, navigation and tool keys (S3776) (#1402) --- crates/ui-egui/src/show.rs | 188 ++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 74 deletions(-) diff --git a/crates/ui-egui/src/show.rs b/crates/ui-egui/src/show.rs index 7055f9b2..a2658391 100644 --- a/crates/ui-egui/src/show.rs +++ b/crates/ui-egui/src/show.rs @@ -739,84 +739,19 @@ fn keyboard(ctx: &egui::Context, show: &mut Show, doc: &Presentation, now: f64, let mut keep = true; let mut actions = vec![]; for (k, m) in keys { - use egui::Key::*; - let presenter_grid = presenter && show.presenter_grid; - let grid_open = if presenter { show.presenter_grid } else { show.grid }; - if grid_open && !matches!(k, Escape | Minus) { + let handled = if grid_open(show, presenter) && !matches!(k, egui::Key::Escape | egui::Key::Minus) { // See All Slides takes no other keys until a slide is chosen. - if k == G && plain(m) { - if presenter_grid { - show.presenter_grid = false; - } else { - show.grid = false; - } + if k == egui::Key::G && plain(m) { + close_grid(show, presenter); + true } else { - continue; + false } } else { - match k { - Escape | Minus => { - let cancelled = k == Escape && show.clear_goto(); - if !cancelled && !show.back_out(presenter) { - keep = false; - } - } - ArrowRight | ArrowDown | Space | PageDown | N => { - if show.ended { - keep = false; - } else { - actions.push(show.state.next(doc)); - } - } - Enter => { - if !show.goto.is_empty() { - if let Some(i) = show.take_goto() - && i < doc.slides.len() - { - actions.push(show.state.goto(doc, i)); - } - } else if show.ended { - keep = false; - } else { - actions.push(show.state.next(doc)); - } - } - Backspace if !show.goto.is_empty() => { - show.goto.pop(); - } - ArrowLeft | ArrowUp | Backspace | PageUp | P if !(k == P && m.command) => { - show.ended = false; - actions.push(show.state.prev(doc)); - } - P if m.command => show.set_pen(!show.pen), - L if m.command => show.set_laser(!show.laser), - A if m.command => show.arrow(), - Home => { - if let Some(i) = show.state.first_index(doc) { - actions.push(show.state.goto(doc, i)); - } - } - End => { - if let Some(i) = show.state.last_index(doc) { - actions.push(show.state.goto(doc, i)); - } - } - B | Period => toggle_blank(show, Color32::BLACK), - W | Comma => toggle_blank(show, Color32::WHITE), - E => show.strokes.clear(), - G if plain(m) => show.open_grid(presenter), - Z if plain(m) => show.zoom_key(), - T if plain(m) => show.timer.toggle(now), - R if plain(m) => show.timer.reset(now), - OpenBracket if plain(m) => show.nudge_notes(-NOTES_STEP), - CloseBracket if plain(m) => show.nudge_notes(NOTES_STEP), - Num0 | Num1 | Num2 | Num3 | Num4 | Num5 | Num6 | Num7 | Num8 | Num9 => { - if let Some(d) = k.name().chars().next() { - show.push_slide_number(d, now); - } - } - _ => continue, - } + navigation_key(show, doc, k, m, presenter, &mut keep, &mut actions) || tool_key(show, k, m, now, presenter) + }; + if !handled { + continue; } // The same key must not also activate a focused presenter button or be handled again // by an embedded presenter viewport. @@ -831,6 +766,111 @@ fn keyboard(ctx: &egui::Context, show: &mut Show, doc: &Presentation, now: f64, keep } +/// Whether the grid that the presenter key G opens is showing in this viewport. +fn grid_open(show: &Show, presenter: bool) -> bool { + if presenter { show.presenter_grid } else { show.grid } +} + +/// Closes the grid that G opens in this viewport. +fn close_grid(show: &mut Show, presenter: bool) { + if presenter && show.presenter_grid { + show.presenter_grid = false; + } else { + show.grid = false; + } +} + +/// Keys that move through the show or end it. False when `k` isn't one of them. +fn navigation_key( + show: &mut Show, + doc: &Presentation, + k: egui::Key, + m: egui::Modifiers, + presenter: bool, + keep: &mut bool, + actions: &mut Vec, +) -> bool { + use egui::Key::*; + match k { + Escape | Minus => { + let cancelled = k == Escape && show.clear_goto(); + if !cancelled && !show.back_out(presenter) { + *keep = false; + } + } + ArrowRight | ArrowDown | Space | PageDown | N => { + if show.ended { + *keep = false; + } else { + actions.push(show.state.next(doc)); + } + } + Enter => { + if !show.goto.is_empty() { + if let Some(i) = show.take_goto() + && i < doc.slides.len() + { + actions.push(show.state.goto(doc, i)); + } + } else if show.ended { + *keep = false; + } else { + actions.push(show.state.next(doc)); + } + } + Backspace if !show.goto.is_empty() => { + show.goto.pop(); + } + ArrowLeft | ArrowUp | Backspace | PageUp => { + show.ended = false; + actions.push(show.state.prev(doc)); + } + P if m.command => show.set_pen(!show.pen), + P => { + show.ended = false; + actions.push(show.state.prev(doc)); + } + Home => { + if let Some(i) = show.state.first_index(doc) { + actions.push(show.state.goto(doc, i)); + } + } + End => { + if let Some(i) = show.state.last_index(doc) { + actions.push(show.state.goto(doc, i)); + } + } + _ => return false, + } + true +} + +/// Pen, laser, blanking, zoom, the timer, note size and typed slide numbers. False when `k` +/// isn't one of them. +fn tool_key(show: &mut Show, k: egui::Key, m: egui::Modifiers, now: f64, presenter: bool) -> bool { + use egui::Key::*; + match k { + L if m.command => show.set_laser(!show.laser), + A if m.command => show.arrow(), + B | Period => toggle_blank(show, Color32::BLACK), + W | Comma => toggle_blank(show, Color32::WHITE), + E => show.strokes.clear(), + G if plain(m) => show.open_grid(presenter), + Z if plain(m) => show.zoom_key(), + T if plain(m) => show.timer.toggle(now), + R if plain(m) => show.timer.reset(now), + OpenBracket if plain(m) => show.nudge_notes(-NOTES_STEP), + CloseBracket if plain(m) => show.nudge_notes(NOTES_STEP), + Num0 | Num1 | Num2 | Num3 | Num4 | Num5 | Num6 | Num7 | Num8 | Num9 => { + if let Some(d) = k.name().chars().next() { + show.push_slide_number(d, now); + } + } + _ => return false, + } + true +} + /// Draw and advance the active show, handling hidden frames, timing, input, transitions, and /// presenter/reading presentation. pub fn ui(app: &mut SlideApp, ui: &mut Ui) {