From b0ef9d610d6d198bc51fde354ae220fddc3e869e Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 17:23:14 -0800 Subject: [PATCH] Dialogs: New Workspace and New Toolbar fit their contents instead of opening 420 pt tall New Workspace, Manage Workspaces, New Toolbar and Manage Toolbars put their OK and Cancel row in a right-to-left layout directly in the modal window. That layout took all the height left in the window's default 420 pt content area and centered the buttons in it, so each dialog opened 420 pt tall with the buttons floating in an empty band. The button row is now as wide as the fields above it and as tall as the buttons, as the shared dialog shell already does (dialogs.rs), so each window ends just below its buttons. --- crates/ui-egui/src/custom_toolbars.rs | 8 +++++-- crates/ui-egui/src/dialogs/tests.rs | 33 +++++++++++++++++++++++++++ crates/ui-egui/src/workspaces.rs | 5 +++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/custom_toolbars.rs b/crates/ui-egui/src/custom_toolbars.rs index fa2be21c0..adbf1223f 100644 --- a/crates/ui-egui/src/custom_toolbars.rs +++ b/crates/ui-egui/src/custom_toolbars.rs @@ -343,7 +343,10 @@ pub(crate) fn show_dialog(app: &mut VectorcraftApp, ctx: &egui::Context) { } }); ui.add_space(16.0); - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + // As wide as the field and as tall as the buttons, as in `dialogs::show`: a right-to-left + // layout would take all the height left in the window and center the buttons in it. + let row = egui::vec2(ui.min_rect().width(), ui.spacing().interact_size.y); + ui.allocate_ui_with_layout(row, egui::Layout::right_to_left(egui::Align::Center), |ui| { if widgets::primary_button(ui, tl!("OK")).clicked() { ok = true; } @@ -445,7 +448,8 @@ pub(crate) fn show_manage(app: &mut VectorcraftApp, ctx: &egui::Context) { } }); ui.add_space(16.0); - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + let row = egui::vec2(ui.min_rect().width(), ui.spacing().interact_size.y); + ui.allocate_ui_with_layout(row, egui::Layout::right_to_left(egui::Align::Center), |ui| { if widgets::primary_button(ui, tl!("OK")).clicked() { ok = true; } diff --git a/crates/ui-egui/src/dialogs/tests.rs b/crates/ui-egui/src/dialogs/tests.rs index 0a9b6d90b..51959c320 100644 --- a/crates/ui-egui/src/dialogs/tests.rs +++ b/crates/ui-egui/src/dialogs/tests.rs @@ -463,6 +463,39 @@ fn dialogs_do_not_stretch_to_the_screen() { assert!(checked >= 10, "only {checked} dialogs drew in the shared frame"); } +#[test] +fn workspace_and_toolbar_dialogs_end_at_their_buttons() { + // New Workspace, Manage Workspaces, New Toolbar and Manage Toolbars draw their own windows: each + // ends just below its OK button, with no empty band above or below the buttons. + for (kind, fields, window) in [ + ("newWorkspace", json!({"name": "Mine"}), "dialog-workspace"), + ("manageWorkspaces", json!({"selected": "", "name": ""}), "dialog-workspace"), + (crate::custom_toolbars::KIND, json!({"name": "Toolbar 1"}), "dialog-new-toolbar"), + (crate::custom_toolbars::MANAGE, json!({"selected": "", "name": ""}), "dialog-manage-toolbars"), + ] { + let mut app = app(); + open(&mut app, kind, fields); + let ctx = egui::Context::default(); + theme::install_fonts(&ctx); + theme::apply(&ctx, Default::default()); + let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1600.0, 1000.0)); + let mut ok = None; + for _ in 0..4 { + let input = egui::RawInput { screen_rect: Some(screen), ..Default::default() }; + let mut out = ctx.run_ui(input, |ui| show(&mut app, ui.ctx())); + out.textures_delta.clear(); + ok = out.shapes.iter().find_map(|c| match &c.shape { + egui::Shape::Text(t) if t.galley.text() == "OK" => Some(t.visual_bounding_rect()), + _ => None, + }); + } + let ok = ok.unwrap_or_else(|| panic!("{kind} draws no OK button")); + let outer = ctx.memory(|m| m.area_rect(egui::Id::unique(window))).unwrap(); + let below = outer.bottom() - ok.bottom(); + assert!(below < 40.0, "{kind}: {below} pt between OK and the bottom of its {} pt window", outer.height()); + } +} + /// The dialog window of `app`'s open dialog after a few frames in a `w` × 900 window. fn dialog_rect(app: &mut VectorcraftApp, w: f32) -> egui::Rect { let ctx = egui::Context::default(); diff --git a/crates/ui-egui/src/workspaces.rs b/crates/ui-egui/src/workspaces.rs index 4b2b31806..d7590ff3b 100644 --- a/crates/ui-egui/src/workspaces.rs +++ b/crates/ui-egui/src/workspaces.rs @@ -519,7 +519,10 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) { ui.label(egui::RichText::new(tl!("Saves the current bars, toolbar and panel layout.")).color(t.text_dim).size(11.0)); } ui.add_space(16.0); - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + // As wide as the fields and as tall as the buttons, as in `dialogs::show`: a right-to-left + // layout would take all the height left in the window and center the buttons in it. + let row = egui::vec2(ui.min_rect().width(), ui.spacing().interact_size.y); + ui.allocate_ui_with_layout(row, egui::Layout::right_to_left(egui::Align::Center), |ui| { if widgets::primary_button(ui, tl!("OK")).clicked() { ok = true; }