diff --git a/crates/topola-egui/src/action.rs b/crates/topola-egui/src/action.rs index 0e4f4c4..348816c 100644 --- a/crates/topola-egui/src/action.rs +++ b/crates/topola-egui/src/action.rs @@ -81,12 +81,16 @@ impl Trigger { } impl Switch { - pub fn toggle_widget(&self, _ctx: &egui::Context, ui: &mut egui::Ui, selected: &mut bool) { + pub fn toggle_widget(&self, ui: &mut egui::Ui, selected: &mut bool) { ui.toggle_value(selected, self.action.widget_text()); } + pub fn checkbox(&self, ui: &mut egui::Ui, selected: &mut bool) { + ui.checkbox(selected, self.action.widget_text()); + } + pub fn consume_key_enabled( - &mut self, + &self, ctx: &egui::Context, _ui: &mut egui::Ui, selected: &mut bool, diff --git a/crates/topola-egui/src/actions.rs b/crates/topola-egui/src/actions.rs index 02a9812..a25cd1c 100644 --- a/crates/topola-egui/src/actions.rs +++ b/crates/topola-egui/src/actions.rs @@ -166,6 +166,7 @@ pub struct ViewActions { pub zoom_to_fit: Switch, pub show_ratsnest: Switch, pub show_navmesh: Switch, + pub show_topo_navmesh: Switch, pub show_bboxes: Switch, pub show_origin_destination: Switch, pub show_appearance_panel: Switch, @@ -177,6 +178,8 @@ impl ViewActions { zoom_to_fit: Action::new_keyless(tr.text("tr-menu-view-zoom-to-fit")).into_switch(), show_ratsnest: Action::new_keyless(tr.text("tr-menu-view-show-ratsnest")).into_switch(), show_navmesh: Action::new_keyless(tr.text("tr-menu-view-show-navmesh")).into_switch(), + show_topo_navmesh: Action::new_keyless(tr.text("tr-menu-view-show-topo-navmesh")) + .into_switch(), show_bboxes: Action::new_keyless(tr.text("tr-menu-view-show-bboxes")).into_switch(), show_origin_destination: Action::new_keyless( tr.text("tr-menu-view-show-origin-destination"), @@ -196,42 +199,30 @@ impl ViewActions { viewport: &mut Viewport, have_workspace: bool, ) { - ui.toggle_value( - &mut viewport.scheduled_zoom_to_fit, - tr.text("tr-menu-view-zoom-to-fit"), - ); + self.zoom_to_fit + .toggle_widget(ui, &mut viewport.scheduled_zoom_to_fit); ui.separator(); - ui.add_enabled_ui(have_workspace, |ui| { - ui.checkbox( - &mut menu_bar.show_ratsnest, - tr.text("tr-menu-view-show-ratsnest"), - ); - ui.checkbox( - &mut menu_bar.show_navmesh, - tr.text("tr-menu-view-show-navmesh"), - ); - ui.checkbox( - &mut menu_bar.show_topo_navmesh, - tr.text("tr-menu-view-show-topo-navmesh"), - ); - ui.checkbox( - &mut menu_bar.show_bboxes, - tr.text("tr-menu-view-show-bboxes"), - ); - ui.checkbox( - &mut menu_bar.show_origin_destination, - tr.text("tr-menu-view-show-origin-destination"), - ); + self.show_ratsnest.checkbox(ui, &mut menu_bar.show_ratsnest); + self.show_navmesh.checkbox(ui, &mut menu_bar.show_navmesh); + self.show_topo_navmesh + .checkbox(ui, &mut menu_bar.show_topo_navmesh); + self.show_bboxes.checkbox(ui, &mut menu_bar.show_bboxes); + self.show_origin_destination + .checkbox(ui, &mut menu_bar.show_origin_destination); }); ui.separator(); + self.show_appearance_panel + .checkbox(ui, &mut menu_bar.show_appearance_panel); - ui.checkbox( - &mut menu_bar.show_appearance_panel, - tr.text("tr-menu-view-show-layer-manager"), - ); + ui.separator(); + ui.label(tr.text("tr-menu-view-kdb-scroll-delta-factor")); + ui.add(egui::widgets::Slider::new( + &mut viewport.kbd_scroll_delta_factor, + 1.0..=100.0, + )); } } @@ -259,7 +250,7 @@ impl PlaceActions { is_placing_via: &mut bool, ) -> egui::InnerResponse<()> { ui.add_enabled_ui(have_workspace, |ui| { - self.place_via.toggle_widget(ctx, ui, is_placing_via); + self.place_via.toggle_widget(ui, is_placing_via); }) } } diff --git a/crates/topola-egui/src/app.rs b/crates/topola-egui/src/app.rs index c99361a..820bb09 100644 --- a/crates/topola-egui/src/app.rs +++ b/crates/topola-egui/src/app.rs @@ -18,8 +18,8 @@ use topola::{ }; use crate::{ - config::Config, error_dialog::ErrorDialog, menu_bar::MenuBar, status_bar::StatusBar, - translator::Translator, viewport::Viewport, workspace::Workspace, + actions::Actions, config::Config, error_dialog::ErrorDialog, menu_bar::MenuBar, + status_bar::StatusBar, translator::Translator, viewport::Viewport, workspace::Workspace, }; pub struct App { diff --git a/crates/topola-egui/src/viewport.rs b/crates/topola-egui/src/viewport.rs index 71cd668..763232d 100644 --- a/crates/topola-egui/src/viewport.rs +++ b/crates/topola-egui/src/viewport.rs @@ -27,10 +27,14 @@ use topola::{ router::navmesh::NavvertexIndex, }; -use crate::{config::Config, menu_bar::MenuBar, painter::Painter, workspace::Workspace}; +use crate::{ + actions::Actions, config::Config, menu_bar::MenuBar, painter::Painter, workspace::Workspace, +}; pub struct Viewport { pub transform: egui::emath::TSTransform, + /// how much should a single arrow key press scroll + pub kbd_scroll_delta_factor: f32, pub scheduled_zoom_to_fit: bool, } @@ -38,6 +42,7 @@ impl Viewport { pub fn new() -> Self { Self { transform: egui::emath::TSTransform::new([0.0, 0.0].into(), 0.01), + kbd_scroll_delta_factor: 5.0, scheduled_zoom_to_fit: false, } } @@ -52,6 +57,7 @@ impl Viewport { egui::CentralPanel::default() .show(ctx, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| { + // TODO: only request re-render if anything changed ui.ctx().request_repaint(); let (id, viewport_rect) = ui.allocate_space(ui.available_size()); @@ -68,7 +74,52 @@ impl Viewport { self.transform.translation += latest_pos.to_vec2() * (old_scaling - self.transform.scaling); - self.transform.translation += ctx.input(|i| i.smooth_scroll_delta); + + // disable built-in behavior of arrow keys + if response.has_focus() { + response.ctx.memory_mut(|m| { + // we are only allowed to modify the focus lock filter if we have focus + m.set_focus_lock_filter( + id, + egui::EventFilter { + horizontal_arrows: true, + vertical_arrows: true, + ..Default::default() + }, + ); + }); + } + + self.transform.translation += ctx.input_mut(|i| { + // handle scrolling + let mut scroll_delta = core::mem::take(&mut i.smooth_scroll_delta); + + // arrow keys + let kbd_sdf = self.kbd_scroll_delta_factor; + let mut pressed = |key| { + i.consume_shortcut(&egui::KeyboardShortcut::new( + egui::Modifiers::SHIFT, + key, + )) + }; + use egui::Key; + scroll_delta.y += if pressed(Key::ArrowDown) { + kbd_sdf + } else if pressed(Key::ArrowUp) { + -kbd_sdf + } else { + 0.0 + }; + scroll_delta.x += if pressed(Key::ArrowRight) { + kbd_sdf + } else if pressed(Key::ArrowLeft) { + -kbd_sdf + } else { + 0.0 + }; + + scroll_delta + }); let mut painter = Painter::new(ui, self.transform, menu_bar.show_bboxes); diff --git a/locales/en-US/main.ftl b/locales/en-US/main.ftl index e61160d..8018d57 100644 --- a/locales/en-US/main.ftl +++ b/locales/en-US/main.ftl @@ -26,6 +26,7 @@ tr-menu-view-show-topo-navmesh = Show Topological Navmesh tr-menu-view-show-bboxes = Show BBoxes tr-menu-view-show-origin-destination = Show Origin–Destination tr-menu-view-show-layer-manager = Show Layer Manager +tr-menu-view-kdb-scroll-delta-factor = Keyboard scroll delta factor tr-menu-view-frame-timestep = Frame Timestep tr-menu-place = Place