From de254a0a6ecbb211c38041f72b9f5b331d589081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ken=20K=C3=B6lzer?= Date: Mon, 2 Nov 2026 14:41:27 +0100 Subject: [PATCH] Ribbon: Font Size value is centered in its box (fixes #3155) The size box draws its value with a frameless TextEdit. The theme floors a text edit at interact_size.y (22 pt), and egui's text edit style aligns its text to the top of that, which wins over the child layout's Align::Center. The digits sat 3.5 pt above the middle of the 24 pt box, 4 pt above the Font name's baseline. The text edit now aligns its text LEFT_CENTER. The new test checks that the value is centered in its box and on the Font name label's baseline. It fails without the change. Co-Authored-By: Claude Sonnet 5.5 --- crates/ui-egui/src/ribbon/home.rs | 3 +++ crates/ui-egui/tests/it/font_size_box.rs | 33 ++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/ribbon/home.rs b/crates/ui-egui/src/ribbon/home.rs index c46447092..7dd55f706 100644 --- a/crates/ui-egui/src/ribbon/home.rs +++ b/crates/ui-egui/src/ribbon/home.rs @@ -622,10 +622,13 @@ fn size_combo(app: &mut SheetApp, ui: &mut Ui, st: &Style) { let arrow_rect = Rect::from_min_max(egui::pos2(frame.right() - 16.0, frame.top() + 1.0), egui::pos2(frame.right() - 1.0, frame.bottom() - 1.0)); let mut field_ui = ui.new_child(egui::UiBuilder::new().max_rect(text_rect.shrink2(vec2(6.0, 0.0))).layout(egui::Layout::left_to_right(egui::Align::Center))); + // The text edit is `interact_size.y` tall and puts its text at the top of that unless told + // otherwise: center it, on the Font name's baseline (#3155). let out = egui::TextEdit::singleline(&mut text) .id(field) .font(theme::ui_font(12.5)) .frame(egui::Frame::NONE) + .align(egui::Align2::LEFT_CENTER) .desired_width(text_rect.width() - 12.0) .show(&mut field_ui); let resp = out.response; diff --git a/crates/ui-egui/tests/it/font_size_box.rs b/crates/ui-egui/tests/it/font_size_box.rs index b34b195ff..f159513c8 100644 --- a/crates/ui-egui/tests/it/font_size_box.rs +++ b/crates/ui-egui/tests/it/font_size_box.rs @@ -1,6 +1,7 @@ -//! Home ▸ Font Size is a box you type a size into, with the standard sizes behind its arrow (#932). +//! Home ▸ Font Size is a box you type a size into, with the standard sizes behind its arrow (#932), +//! and the size sits in the middle of that box (#3155). -use egui::{Event, Key, Modifiers, accesskit::Role}; +use egui::{Event, Key, Modifiers, Rect, Shape, accesskit::Role}; use egui_kittest::kittest::Queryable as _; use gridcraft_engine::Session; use gridcraft_engine::core::{CellRef, Value}; @@ -124,3 +125,31 @@ fn the_arrow_opens_the_plain_list_of_sizes() { h.run_steps(3); assert_eq!(size(&h, "A1"), 12.0, "Down from 11 then Enter picks 12"); } + +/// The on-screen box of the painted text `text` that overlaps `within`. The grid's row headers +/// paint "11" too, so the size has to be looked for inside its own box. +fn painted_text(h: &Harness, text: &str, within: Rect) -> Rect { + h.output() + .shapes + .iter() + .find_map(|s| match &s.shape { + Shape::Text(t) if t.galley.job.text == text => { + let rect = t.galley.rect.translate(t.pos.to_vec2()); + within.intersects(rect).then_some(rect) + } + _ => None, + }) + .unwrap_or_else(|| panic!("{text:?} is painted inside {within:?}")) +} + +#[test] +/// A text edit aligns its text to the top of its rect unless told otherwise, which left the size +/// 4 pt above the Font name's baseline. +fn the_size_is_vertically_centered_in_its_box() { + let h = harness(); + let field = h.get_by_role_and_label(Role::TextInput, "Font Size").rect(); + let value = painted_text(&h, "11", field); + let name = painted_text(&h, "Calibri", Rect::EVERYTHING); + assert!((value.center().y - field.center().y).abs() <= 1.0, "the size is centered in its box: {value:?} in {field:?}"); + assert!((value.center().y - name.center().y).abs() <= 1.0, "the size is on the Font name's baseline: {value:?} against {name:?}"); +}