From 89439636d88fce4115799eb3ec7a067b3476e104 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo Date: Wed, 14 Oct 2026 08:08:41 +0200 Subject: [PATCH] Dialogs move by their title bar instead of staying pinned to the centre (fixes #1250) --- crates/ui-egui/src/dialogs.rs | 4 +- crates/ui-egui/tests/dialog_move.rs | 70 +++++++++++++++++++++++++++++ docs/ui-parity.md | 6 ++- 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 crates/ui-egui/tests/dialog_move.rs diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index fb899c702..d00fbe807 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -1040,7 +1040,9 @@ pub fn show(app: &mut SheetApp, ctx: &egui::Context) { .collapsible(false) .resizable(false) .default_width(width) - .anchor(egui::Align2::CENTER_CENTER, vec2(0.0, -40.0)) + // A default position, not an anchor: egui anchors can't be dragged, and dialogs move by their title bar. + .pivot(egui::Align2::CENTER_CENTER) + .default_pos(ctx.content_rect().center() + vec2(0.0, -40.0)) .open(&mut win_open); let window = if d.name == "insertPicture" { window.default_height(240.0) } else { window }; window.show(ctx, |ui| { diff --git a/crates/ui-egui/tests/dialog_move.rs b/crates/ui-egui/tests/dialog_move.rs new file mode 100644 index 000000000..7548342c7 --- /dev/null +++ b/crates/ui-egui/tests/dialog_move.rs @@ -0,0 +1,70 @@ +//! Dialogs can be dragged by their title bar, like Excel's, and stay where they are dropped. + +use egui::{Event, Modifiers, PointerButton, vec2}; +use gridcraft_engine::Session; +use gridcraft_ui_egui::SheetApp; +use serde_json::json; + +type Harness = egui_kittest::Harness<'static, SheetApp>; + +fn harness() -> Harness { + 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 dialog_rect(h: &Harness, name: &str) -> egui::Rect { + h.ctx.memory(|m| m.area_rect(egui::Id::new("dialog").with(name))).unwrap() +} + +fn button(h: &mut Harness, pos: egui::Pos2, pressed: bool) { + h.input_mut().events.push(Event::PointerButton { pos, button: PointerButton::Primary, pressed, modifiers: Modifiers::NONE }); + h.run_steps(2); +} + +fn drag_title_bar(h: &mut Harness, name: &str, by: egui::Vec2) { + let start = dialog_rect(h, name).center_top() + vec2(0.0, 10.0); + h.input_mut().events.push(Event::PointerMoved(start)); + h.run_steps(2); + button(h, start, true); + for step in 1..=4 { + h.input_mut().events.push(Event::PointerMoved(start + by * (step as f32 / 4.0))); + h.run_steps(1); + } + button(h, start + by, false); +} + +#[test] +fn dragging_the_find_and_replace_title_bar_moves_the_dialog_and_it_stays_there() { + let mut h = harness(); + h.state_mut().open_dialog("find", json!({})); + h.run_steps(6); + let before = dialog_rect(&h, "find"); + drag_title_bar(&mut h, "find", vec2(120.0, 80.0)); + h.run_steps(10); + let after = dialog_rect(&h, "find"); + assert_eq!(after.min - before.min, vec2(120.0, 80.0), "dialog went from {before:?} to {after:?}"); + assert!(h.state().dialog.is_some(), "the drag does not close the dialog"); +} + +#[test] +fn go_to_format_cells_and_sort_can_be_dragged_too() { + for name in ["goTo", "formatCells", "sort"] { + let mut h = harness(); + h.state_mut().open_dialog(name, json!({})); + h.run_steps(6); + let before = dialog_rect(&h, name); + drag_title_bar(&mut h, name, vec2(-100.0, 60.0)); + h.run_steps(10); + let after = dialog_rect(&h, name); + assert_eq!(after.min - before.min, vec2(-100.0, 60.0), "{name} went from {before:?} to {after:?}"); + } +} diff --git a/docs/ui-parity.md b/docs/ui-parity.md index 22e221e69..2707c69e4 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -1,6 +1,6 @@ # UI parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (horizontal scrollbar in the sheet tab bar, #840) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** minor (dialogs move by their title bar, #1250) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 Interaction, controls and feel, against Excel. Part of [target-app-parity.md](target-app-parity.md). **UI/UX fidelity: ~55% ready, 50–80 h** (estimated). Ribbon command coverage is measured @@ -14,6 +14,7 @@ Sources: `crates/ui-egui/src` (ribbon, grid, editor, formula bar, dialogs, panes | Element | Excel | GridCraft | Status | |---|---|---|---| +| 2026-10-14 | minor | Dialogs (Find and Replace, Go To, Format Cells, Sort and the rest) move by their title bar instead of staying pinned to the centre (#1250) | | Title bar, Quick Access Toolbar, AutoSave toggle | yes | yes | done; macOS window controls misaligned (#170), Dock icon size (#169) | | Ribbon: tabs, groups, split buttons, galleries, contextual tabs | yes | yes (Table Design, Chart Design, Format, PivotTable, Header & Footer tabs) | done; missing contextual tabs for pictures, shapes, sparklines, slicers | | Ribbon collapse, simplified ribbon, customize ribbon/QAT | yes | partial | customization missing (File ▸ Options is the one missing File command) | @@ -137,7 +138,8 @@ Format Cells, Insert Function/Formula Builder, Find and Replace, Go To and Go To Name Manager, Data Validation, Paste Special, Conditional Formatting manager, Page Setup, Goal Seek, Scenario Manager, Data Analysis, Forecast Sheet and others exist. Missing or partial: Options, Solver, Power Query editor, Insert Object, Equation editor, Protect/Allow Edit Ranges, -Workbook Links, Accessibility checker. +Workbook Links, Accessibility checker. Like Excel's, every dialog opens centred and moves by its +title bar, keeping its place while it is open (#1250). ## Accessibility