HU1: cover Hungarian flyouts in narrow viewports

This commit is contained in:
macadminHU
2026-11-01 11:26:50 +01:00
committed by GitHub
parent becb09900b
commit 7c42fd74e3
+86 -9
View File
@@ -24,21 +24,21 @@ fn rect(h: &egui_kittest::Harness<'static, test_window::Window>, label: &str) ->
h.get_by_label(label).rect()
}
/// Collects painted text bounds and their clip rectangles, including nested shapes.
fn collect_text(shape: &egui::Shape, clip: egui::Rect, texts: &mut Vec<(String, egui::Rect, egui::Rect)>) {
match shape {
egui::Shape::Text(text) => texts.push((text.galley.text().to_owned(), text.visual_bounding_rect(), clip)),
egui::Shape::Vec(shapes) => shapes.iter().for_each(|shape| collect_text(shape, clip, texts)),
_ => {}
}
}
/// Checks translated tooltips and right-click flyout rows in both Tools-panel layouts,
/// including painted labels, unchanged shortcuts and unclipped, nonoverlapping text.
#[test]
fn hungarian_tool_buttons_translate_every_tool_and_keep_shortcuts() {
use egui::{Event, Modifiers, PointerButton};
/// Collects painted text bounds and their clip rectangles, including nested shapes.
fn collect_text(shape: &egui::Shape, clip: egui::Rect, texts: &mut Vec<(String, egui::Rect, egui::Rect)>) {
match shape {
egui::Shape::Text(text) => texts.push((text.galley.text().to_owned(), text.visual_bounding_rect(), clip)),
egui::Shape::Vec(shapes) => shapes.iter().for_each(|shape| collect_text(shape, clip, texts)),
_ => {}
}
}
for double in [false, true] {
let mut app = app(double);
app.ui.language = "hu".into();
@@ -113,6 +113,83 @@ fn hungarian_tool_buttons_translate_every_tool_and_keep_shortcuts() {
}
}
/// Keeps long translated flyout rows reachable by scrolling in a narrow viewport,
/// preserving the custom shortcut and selection through actual pointer input.
#[test]
fn hungarian_flyout_scrolls_horizontally_in_narrow_windows() {
use egui::{Event, Modifiers, PointerButton};
for double in [false, true] {
for width in [180.0, 240.0] {
let mut app = app(double);
app.ui.language = "hu".into();
let chord = "Ctrl+Alt+Shift+F12";
app.run(
"window.setShortcut",
serde_json::json!({"id": "tool.select", "params": {"tool": "ellipseFrame"}, "shortcut": chord, "steal": true}),
)
.unwrap();
app.select_tool("rectangleFrame");
let mut h = test_window::open(app, vec2(width, 1000.0));
let at = rect(&h, "Téglalapkeret eszköz (F)").center();
h.input_mut().events.push(Event::PointerMoved(at));
for pressed in [true, false] {
h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Secondary, pressed, modifiers: Modifiers::NONE });
}
h.run_steps(3);
let gi = h.state().app.ui.flyout.unwrap();
let area = h.ctx.memory(|m| m.area_rect(egui::Id::unique(("flyout", gi)))).unwrap();
let viewport = h.ctx.content_rect();
assert!(viewport.expand(0.5).contains_rect(area), "flyout {area:?} exceeds viewport {viewport:?}");
let label = "Ellipsziskeret eszköz";
let shortcut = crate::menus::shortcut_text(chord);
let painted = |h: &egui_kittest::Harness<'static, test_window::Window>, text: &str| {
let row = rect(h, label);
let mut texts = Vec::new();
for shape in &h.output().shapes {
collect_text(&shape.shape, shape.clip_rect, &mut texts);
}
let (_, bounds, clip) = texts.into_iter().find(|(t, b, _)| t == text && row.contains(b.center())).unwrap();
(bounds, clip)
};
let (label_bounds, label_clip) = painted(&h, label);
assert!(label_clip.contains_rect(label_bounds), "label must be readable at the start");
let (before, clip) = painted(&h, &shortcut);
let oversized = rect(&h, label).width() > clip.width();
if width == 180.0 {
assert!(oversized, "the tighter case must exercise horizontal overflow on every platform");
}
review_shot(&mut h, &format!("flyout-{width}-double-{double}-left.png"));
if oversized {
assert!(!clip.contains_rect(before), "the shortcut starts beyond the narrow viewport");
wheel(&mut h, area.center(), vec2(-1000.0, 0.0));
let (after, clip) = painted(&h, &shortcut);
assert!(clip.contains_rect(after), "scrolling must make the complete shortcut readable");
assert!(after.left() < before.left(), "horizontal input must move the row");
} else {
assert!(clip.contains_rect(before));
}
review_shot(&mut h, &format!("flyout-{width}-double-{double}-right.png"));
assert_eq!(crate::menus::tool_shortcut_label(&h.state().app, "ellipseFrame"), Some(shortcut));
let at = rect(&h, label).intersect(area).center();
h.input_mut().events.push(Event::PointerMoved(at));
for pressed in [true, false] {
h.input_mut().events.push(Event::PointerButton { pos: at, button: PointerButton::Primary, pressed, modifiers: Modifiers::NONE });
}
h.run_steps(3);
assert_eq!(h.state().app.session.tool_id(), "ellipseFrame");
assert!(h.state().app.ui.flyout.is_none());
}
}
}
/// Saves synthetic UI evidence only when the local review explicitly requests it.
fn review_shot(h: &mut egui_kittest::Harness<'static, test_window::Window>, name: &str) {
if let Some(dir) = std::env::var_os("DESIGNCRAFT_HU_REVIEW_SHOTS") {
h.render().unwrap().save(std::path::Path::new(&dir).join(name)).unwrap();
}
}
/// As InDesign's: a tool group's flyout closes on Esc and on a click outside it (the fill
/// swatch, a panel), not only on the canvas.
#[test]