From 85c7fc4d6e529ee310a87929409101d08d76d6b2 Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Mon, 12 Oct 2026 08:32:27 +0200 Subject: [PATCH] Zoom dialog: a Magnification choice sets the percentage to store (#521) --- crates/ui-egui/src/control.rs | 2 +- crates/ui-egui/src/dialogs.rs | 13 ++++- crates/ui-egui/tests/zoom_dialog.rs | 85 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 crates/ui-egui/tests/zoom_dialog.rs diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs index 6f6280ef7..ef9dddd6f 100644 --- a/crates/ui-egui/src/control.rs +++ b/crates/ui-egui/src/control.rs @@ -232,7 +232,7 @@ pub fn handle(app: &mut SheetApp, ctx: &egui::Context, method: &str, p: &Json) - } else if field == "search" { d.search = s("value").unwrap_or("").to_string(); } else { - d.values.insert(field.to_string(), p.get("value").cloned().unwrap_or(Json::Null)); + d.set_value(field, p.get("value").cloned().unwrap_or(Json::Null)); } ok(json!(d.values)) } diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 5e859c68e..da6b49748 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -47,6 +47,17 @@ impl Dialog { &self.name } + /// Sets a form value. In Zoom, a Magnification choice is also the percentage `view.zoom` stores. + pub(crate) fn set_value(&mut self, key: &str, value: Json) { + if self.name == "zoom" + && key == "preset" + && let Some(p) = value.as_str().and_then(|s| s.parse::().ok()) + { + self.values.insert("percent".into(), json!(p)); + } + self.values.insert(key.into(), value); + } + fn form(name: &str, title: &str, command: &'static str, fields: Vec, defaults: Json) -> Dialog { Dialog { name: name.into(), @@ -1288,7 +1299,7 @@ fn form_fields(ui: &mut egui::Ui, d: &mut Dialog) { let cur = d.values.get(key).and_then(Json::as_str).unwrap_or("").to_string(); for (val, text) in options { if ui.radio(cur == val, text).clicked() { - d.values.insert(key.into(), json!(val)); + d.set_value(key, json!(val)); } } }); diff --git a/crates/ui-egui/tests/zoom_dialog.rs b/crates/ui-egui/tests/zoom_dialog.rs new file mode 100644 index 000000000..f5be90833 --- /dev/null +++ b/crates/ui-egui/tests/zoom_dialog.rs @@ -0,0 +1,85 @@ +//! The Zoom dialog stores the Magnification the user picks. + +use egui::vec2; +use egui_kittest::kittest::Queryable; +use gridcraft_engine::Session; +use gridcraft_ui_egui::SheetApp; +use gridcraft_ui_egui::control::{Outcome, handle}; +use serde_json::{Value as Json, json}; + +fn harness() -> egui_kittest::Harness<'static, SheetApp> { + let mut session = Session::new(); + session.new_workbook(); + let mut h = egui_kittest::Harness::builder().with_size(vec2(1200.0, 800.0)).build_ui_state( + |ui, app: &mut SheetApp| { + app.logic(&ui.ctx().clone()); + app.ui(ui); + }, + SheetApp::new(session, Default::default()), + ); + h.run_steps(6); + h +} + +fn zoom(h: &egui_kittest::Harness<'static, SheetApp>) -> u16 { + h.state().session.active().unwrap().wb.active().unwrap().zoom +} + +fn control(h: &mut egui_kittest::Harness<'static, SheetApp>, method: &str, params: Json) -> Json { + let ctx = h.ctx.clone(); + match handle(h.state_mut(), &ctx, method, ¶ms) { + Outcome::Done(v) => v, + Outcome::Screenshot { .. } => json!(null), + } +} + +#[test] +fn choosing_a_magnification_and_pressing_ok_sets_that_zoom() { + let mut h = harness(); + h.state_mut().run("view.zoom", json!({"percent": 160})).unwrap(); + h.state_mut().open_dialog("zoom", json!({})); + h.run_steps(6); + h.get_by_label("50%").click(); + h.run_steps(6); + h.get_by_label(" OK ").click(); + h.run_steps(6); + assert!(h.state().dialog.is_none()); + assert_eq!(zoom(&h), 50); +} + +#[test] +fn choosing_a_magnification_and_confirming_by_command_sets_that_zoom() { + let mut h = harness(); + h.state_mut().run("view.zoom", json!({"percent": 180})).unwrap(); + h.state_mut().open_dialog("zoom", json!({})); + h.run_steps(6); + h.get_by_label("75%").click(); + h.run_steps(6); + let r = control(&mut h, "ui.dialog.confirm", json!({})); + assert_eq!(r["ok"], json!(true), "{r}"); + assert_eq!(zoom(&h), 75); +} + +#[test] +fn setting_the_magnification_over_the_control_channel_sets_that_zoom() { + let mut h = harness(); + h.state_mut().run("view.zoom", json!({"percent": 180})).unwrap(); + control(&mut h, "ui.dialog", json!({"name": "zoom"})); + control(&mut h, "ui.dialog.set", json!({"field": "preset", "value": "25"})); + let r = control(&mut h, "ui.dialog.confirm", json!({})); + assert_eq!(r["ok"], json!(true), "{r}"); + assert_eq!(zoom(&h), 25); +} + +#[test] +fn a_custom_percentage_after_a_magnification_wins_and_an_unedited_ok_keeps_the_zoom() { + let mut h = harness(); + control(&mut h, "ui.dialog", json!({"name": "zoom"})); + control(&mut h, "ui.dialog.set", json!({"field": "preset", "value": "25"})); + control(&mut h, "ui.dialog.set", json!({"field": "percent", "value": 225})); + control(&mut h, "ui.dialog.confirm", json!({})); + assert_eq!(zoom(&h), 225); + control(&mut h, "ui.dialog", json!({"name": "zoom"})); + control(&mut h, "ui.dialog.confirm", json!({})); + assert_eq!(zoom(&h), 225); +}