M5: the hotbar settings button shows one tooltip (#6548) (#6550)

This commit is contained in:
mtlcl410 authored and GitHub committed 2026-11-09 08:56:52 +08:00
1 parent bb8fbd6b67
commit 04062a047e
3 files changed
+43 -2

No files matched your search

+1 -1
View File
@@ -112,7 +112,7 @@ impl Hotbar {
fn settings_button(ui: &mut egui::Ui, cell: f32, picker_open: &mut bool) -> bool {
let settings = ui
.push_id("hotbar-settings", |ui| {
icons::button(ui, "settings", cell, false, tl!("Hotbar settings")).on_hover_text(tl!("Hotbar settings / add tools"))
icons::labeled_button(ui, "settings", cell, false, tl!("Hotbar settings"), tl!("Hotbar settings / add tools"))
})
.inner;
if settings.clicked() {
+8 -1
View File
@@ -34,7 +34,14 @@ pub fn paint(ui: &egui::Ui, rect: Rect, name: &str, size: f32, tint: Color32) {
}
/// Square icon button: transparent until hovered; `selected` gets the accent treatment.
/// `tooltip` is both its accessible name and its one tooltip.
pub fn button(ui: &mut egui::Ui, name: &str, box_size: f32, selected: bool, tooltip: &str) -> Response {
labeled_button(ui, name, box_size, selected, tooltip, tooltip)
}
/// [`button`] whose tooltip says more than its accessible name (`label`). It shows that one
/// tooltip, so callers add no `on_hover_text` of their own (#6548: two tooltips stacked).
pub fn labeled_button(ui: &mut egui::Ui, name: &str, box_size: f32, selected: bool, label: &str, tooltip: &str) -> Response {
let t = Tokens::get(ui.ctx());
// The shared button paints no fill of its own: the eased press wash below replaces it.
let clear = |icon| ButtonVisuals { fill: Color32::TRANSPARENT, stroke: Stroke::NONE, icon };
@@ -46,7 +53,7 @@ pub fn button(ui: &mut egui::Ui, name: &str, box_size: f32, selected: bool, tool
corner_radius: t.radius.into(),
focus_stroke: Stroke::new(1.0, t.accent),
};
let label = if tooltip.is_empty() { name } else { tooltip };
let label = if label.is_empty() { name } else { label };
// The wash eases from the response, so reserve its place under the icon and focus ring.
let wash = ui.painter().add(egui::Shape::Noop);
let mut painted = None;
+34
View File
@@ -3590,6 +3590,40 @@ fn hotbar_picker_adds_and_runs_freehand_highlight() {
assert_eq!(h.state().quick_tool, QuickTool::Comment(pdfcraft_ui_egui::comments::CommentTool::FreehandHighlight));
}
/// #6548: resting on the hotbar's gear showed two stacked tooltips, "Hotbar settings" and
/// "Hotbar settings / add tools". It shows the longer one only and keeps its short name.
#[test]
fn hotbar_settings_button_shows_one_tooltip() {
let mut h = harness(|_| {});
h.run_steps(2);
h.get_by_label("Hotbar settings").hover();
// egui shows a tooltip once the pointer has rested `tooltip_delay` seconds of *input* time,
// and the harness advances that clock by a fixed step every frame, so the wait is counted in
// simulated seconds rather than slept: it cannot pass early or depend on the machine's speed.
let delay = f64::from(h.ctx.global_style().interaction.tooltip_delay);
let start = h.ctx.input(|i| i.time);
let elapsed = |h: &Harness<'static, PdfCraftApp>| h.ctx.input(|i| i.time) - start;
// The button's name; a second tooltip repeating it would make two. Checked after every
// frame, so one that shows only briefly is caught too.
let names = |h: &Harness<'static, PdfCraftApp>| h.query_all_by_label("Hotbar settings").count();
let mut frames = 0;
while h.query_all_by_label("Hotbar settings / add tools").next().is_none() {
assert!(elapsed(&h) < 4.0 * delay && frames < 100, "no tooltip after {:.2}s of rest", elapsed(&h));
h.step();
frames += 1;
assert_eq!(names(&h), 1, "a second tooltip at {:.2}s", elapsed(&h));
}
// Rest two more delays, so a second tooltip would have had its chance to open.
let shown = elapsed(&h);
while elapsed(&h) < shown + 2.0 * delay && frames < 100 {
h.step();
frames += 1;
assert_eq!(names(&h), 1, "a second tooltip at {:.2}s", elapsed(&h));
}
assert_eq!(h.query_all_by_label("Hotbar settings / add tools").count(), 1, "the tooltip shows");
assert_eq!(names(&h), 1, "the button's name, and no second tooltip");
}
#[test]
fn hotbar_picker_searches_translated_tool_labels() {
if crate::support::skip_without_catalogs("hotbar_picker_searches_translated_tool_labels") {