From 58d00e78d5ccb6847d013110ca3c562d824eb763 Mon Sep 17 00:00:00 2001 From: Markus Ang Date: Thu, 22 Oct 2026 19:41:49 -0400 Subject: [PATCH] #2034: fit translated Settings page names --- crates/ui-egui/src/panels/settings.rs | 15 +++++++++++---- crates/ui-egui/tests/ui_scrolling.rs | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/ui-egui/src/panels/settings.rs b/crates/ui-egui/src/panels/settings.rs index 28a7c014..a386367d 100644 --- a/crates/ui-egui/src/panels/settings.rs +++ b/crates/ui-egui/src/panels/settings.rs @@ -589,6 +589,7 @@ fn browser_storage_ui(app: &mut EffectcraftApp, ui: &mut egui::Ui, t: &Tokens, a ui.ctx().request_repaint_after(std::time::Duration::from_secs(1)); } +/// Draw the editable label colors and names in Settings. fn labels_ui(app: &mut EffectcraftApp, ui: &mut egui::Ui, cur: &Value, acts: &mut Vec) { ui.label(tr("Label Colors and Names:")); ui.add_space(4.0); @@ -622,6 +623,7 @@ fn labels_ui(app: &mut EffectcraftApp, ui: &mut egui::Ui, cur: &Value, acts: &mu } } +/// Draw the Settings dialog, including its translated page list and the selected page's controls. pub fn show(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) { let all = pages(); let mut page = app.dialog_state.settings_page.clone(); @@ -661,28 +663,33 @@ pub fn show(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) { { let ui = &mut body; // Page list (left, like After Effects). + let widest_page = + all.iter().map(|p| ui.painter().layout_no_wrap(tr(p.title).to_owned(), Tokens::ui(12.5), t.text).size().x).fold(0.0_f32, f32::max); + let page_width = (widest_page + 20.0).max(176.0).min((ui.available_width() * 0.42).min(300.0)); ui.vertical(|ui| { - ui.set_width(180.0); + ui.set_width(page_width + 4.0); egui::ScrollArea::vertical().id_salt("settings-pages").max_height(body_h).auto_shrink([false, false]).show(ui, |ui| { // The rows touch, so the pointer never falls between two of them. ui.spacing_mut().item_spacing.y = 0.0; for p in &all { - let (r, resp) = ui.allocate_exact_size(vec2(176.0, 24.0), egui::Sense::click()); + let (r, resp) = ui.allocate_exact_size(vec2(page_width, 24.0), egui::Sense::click()); let sel = page == p.id; if sel { ui.painter().rect_filled(r, 3.0, t.accent); } else if resp.hovered() { ui.painter().rect_filled(r, 3.0, t.hover); } - ui.painter().text( + crate::widgets::text_fit( + ui.painter(), r.left_center() + vec2(10.0, 0.0), egui::Align2::LEFT_CENTER, tr(p.title), Tokens::ui(12.5), + (page_width - 20.0).max(0.0), if sel { Color32::WHITE } else { t.text }, ); app.auto.add(&format!("settings.page.{}", p.id), r, p.title); - if resp.clicked() { + if resp.on_hover_text(tr(p.title)).clicked() { page = p.id.to_string(); } } diff --git a/crates/ui-egui/tests/ui_scrolling.rs b/crates/ui-egui/tests/ui_scrolling.rs index 5f681623..85cca07f 100644 --- a/crates/ui-egui/tests/ui_scrolling.rs +++ b/crates/ui-egui/tests/ui_scrolling.rs @@ -8,6 +8,7 @@ use egui_kittest::Harness; use egui_kittest::kittest::Queryable; use serde_json::json; +/// Open the demo project in a UI test harness with the requested window size. fn harness(w: f32, h: f32) -> Harness<'static, EffectcraftApp> { let mut s = Session::default(); s.execute("file.openDemoProject", json!({})).unwrap(); @@ -16,6 +17,7 @@ fn harness(w: f32, h: f32) -> Harness<'static, EffectcraftApp> { h } +/// Return a registered widget's rectangle so UI tests can inspect its layout. fn rect(h: &Harness<'_, EffectcraftApp>, id: &str) -> Rect { let e = h.state().auto.find(id).unwrap_or_else(|| panic!("no {id}")); Rect::from_min_size(pos2(e.rect[0], e.rect[1]), vec2(e.rect[2], e.rect[3])) @@ -163,3 +165,22 @@ fn settings_dialog_does_not_scroll_sideways() { h.run_steps(20); assert_eq!((rect(&h, "settings.ok"), rect(&h, "settings.page.general")), (ok, page), "nothing moved sideways"); } + +/// #2034: the Settings sidebar uses the translated page names when deciding its width. +#[test] +fn settings_page_column_fits_japanese_names() { + use effectcraft_ui_egui::theme::Tokens; + + let mut session = Session::default(); + session.prefs.general.language = "ja".into(); + let mut h = Harness::builder().with_size(vec2(1400.0, 900.0)).build_eframe(|_| EffectcraftApp::new(session)); + h.run_steps(3); + let ctx = h.ctx.clone(); + effectcraft_ui_egui::menus::invoke(h.state_mut(), &ctx, "app.settings", json!({"page": "scripting"})).unwrap(); + h.run_steps(3); + + let name = "スクリプトとエクスプレッション"; + let text_width = h.ctx.fonts_mut(|fonts| fonts.layout_no_wrap(name.into(), Tokens::ui(12.5), egui::Color32::WHITE).size().x); + let row = rect(&h, "settings.page.scripting"); + assert!(row.width() >= text_width + 20.0, "{name} needs {text_width} points; row is {row:?}"); +}