Skip to content

Commit

Permalink
Once you have waited for a tooltip to show, show the next one right a…
Browse files Browse the repository at this point in the history
…way (#4585)

* Closes #4582

User-story: there are multiple icons in a row, and the user wants them
explained. They hover over one until the tooltips appears. They then
move on to the next and don't want to wait for that tooltip again.
  • Loading branch information
emilk authored May 30, 2024
1 parent 89968e6 commit a7eed0a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 20 deletions.
61 changes: 42 additions & 19 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,14 +584,7 @@ impl Response {
return true;
}

if self.context_menu_opened() {
return false;
}

if ComboBox::is_open(&self.ctx, self.id) {
return false; // Don't cover the open ComboBox with a tooltip
}

// Fast early-outs:
if self.enabled {
if !self.hovered || !self.ctx.input(|i| i.pointer.has_pointer()) {
return false;
Expand All @@ -600,20 +593,44 @@ impl Response {
return false;
}

if self.ctx.style().interaction.show_tooltips_only_when_still {
// We only show the tooltip when the mouse pointer is still,
// but once shown we keep showing it until the mouse leaves the parent.
if self.context_menu_opened() {
return false;
}

if !self.ctx.input(|i| i.pointer.is_still()) && !self.is_tooltip_open() {
// wait for mouse to stop
self.ctx.request_repaint();
return false;
}
if ComboBox::is_open(&self.ctx, self.id) {
return false; // Don't cover the open ComboBox with a tooltip
}

if !self.is_tooltip_open() {
let time_til_tooltip = self.ctx.style().interaction.tooltip_delay
- self.ctx.input(|i| i.pointer.time_since_last_movement());
let when_was_a_toolip_last_shown_id = Id::new("when_was_a_toolip_last_shown");
let now = self.ctx.input(|i| i.time);

let when_was_a_toolip_last_shown = self
.ctx
.data(|d| d.get_temp::<f64>(when_was_a_toolip_last_shown_id));

let tooltip_delay = self.ctx.style().interaction.tooltip_delay;
let tooltip_grace_time = self.ctx.style().interaction.tooltip_grace_time;

// There is a tooltip_delay before showing the first tooltip,
// but once one tooltips is show, moving the mouse cursor to
// another widget should show the tooltip for that widget right away.

// Let the user quickly move over some dead space to hover the next thing
let tooltip_was_recently_shown = when_was_a_toolip_last_shown
.map_or(false, |time| ((now - time) as f32) < tooltip_grace_time);

if !tooltip_was_recently_shown && !self.is_tooltip_open() {
if self.ctx.style().interaction.show_tooltips_only_when_still {
// We only show the tooltip when the mouse pointer is still.
if !self.ctx.input(|i| i.pointer.is_still()) {
// wait for mouse to stop
self.ctx.request_repaint();
return false;
}
}

let time_til_tooltip =
tooltip_delay - self.ctx.input(|i| i.pointer.time_since_last_movement());

if 0.0 < time_til_tooltip {
// Wait until the mouse has been still for a while
Expand All @@ -633,6 +650,12 @@ impl Response {
return false;
}

// All checks passed: show the tooltip!

// Remember that we're showing a tooltip
self.ctx
.data_mut(|data| data.insert_temp::<f64>(when_was_a_toolip_last_shown_id, now));

true
}

Expand Down
22 changes: 21 additions & 1 deletion crates/egui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,13 @@ pub struct Interaction {
/// Delay in seconds before showing tooltips after the mouse stops moving
pub tooltip_delay: f32,

/// If you have waited for a tooltip and then hover some other widget within
/// this many seconds, then show the new tooltip right away,
/// skipping [`Self::tooltip_delay`].
///
/// This lets the user quickly move over some dead space to hover the next thing.
pub tooltip_grace_time: f32,

/// Can you select the text on a [`crate::Label`] by default?
pub selectable_labels: bool,

Expand Down Expand Up @@ -1102,7 +1109,8 @@ impl Default for Interaction {
resize_grab_radius_corner: 10.0,
interact_radius: 5.0,
show_tooltips_only_when_still: true,
tooltip_delay: 0.3,
tooltip_delay: 0.5,
tooltip_grace_time: 0.2,
selectable_labels: true,
multi_widget_text_select: true,
}
Expand Down Expand Up @@ -1590,6 +1598,7 @@ impl Interaction {
resize_grab_radius_corner,
show_tooltips_only_when_still,
tooltip_delay,
tooltip_grace_time,
selectable_labels,
multi_widget_text_select,
} = self;
Expand Down Expand Up @@ -1623,6 +1632,17 @@ impl Interaction {
.suffix(" s"),
);
ui.end_row();

ui.label("Tooltip grace time").on_hover_text(
"If a tooltip is open and you hover another widget within this grace period, show the next tooltip right away",
);
ui.add(
DragValue::new(tooltip_grace_time)
.clamp_range(0.0..=1.0)
.speed(0.05)
.suffix(" s"),
);
ui.end_row();
});

ui.checkbox(
Expand Down

0 comments on commit a7eed0a

Please sign in to comment.