Skip to content

Commit

Permalink
Only show one tooltip per layer at a time
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Jul 3, 2024
1 parent bb394df commit 9fb9887
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
7 changes: 6 additions & 1 deletion crates/egui/src/containers/popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,12 @@ fn show_tooltip_at_dyn<'c, R>(
}

// if there are multiple tooltips open they should use the same common_id for the `tooltip_size` caching to work.
let mut state = ctx.frame_state(|fs| {
let mut state = ctx.frame_state_mut(|fs| {
// Remember that this is the widget showing the tooltip:
fs.tooltip_state
.per_layer_tooltip_widget
.insert(parent_layer, widget_id);

fs.tooltip_state
.widget_tooltips
.get(&widget_id)
Expand Down
19 changes: 15 additions & 4 deletions crates/egui/src/frame_state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
use crate::{id::IdSet, *};

/// Reset at the start of each frame.
#[derive(Clone, Debug, Default)]
pub struct TooltipFrameState {
/// If a tooltip has been shown this frame, where was it?
/// This is used to prevent multiple tooltips to cover each other.
pub widget_tooltips: IdMap<PerWidgetTooltipState>,

/// For each layer, which widget is showing a tooltip (if any)?
///
/// Only one widget per layer may show a tooltip.
/// But if a tooltip contains a tooltip, you can show a tooltip on top of a tooltip.
pub per_layer_tooltip_widget: ahash::HashMap<LayerId, Id>,
}

impl TooltipFrameState {
pub fn clear(&mut self) {
self.widget_tooltips.clear();
let Self {
widget_tooltips,
per_layer_tooltip_widget,
} = self;
widget_tooltips.clear();
per_layer_tooltip_widget.clear();
}
}

Expand Down Expand Up @@ -51,9 +65,6 @@ pub struct FrameState {
/// How much space is used by panels.
pub used_by_panels: Rect,

/// If a tooltip has been shown this frame, where was it?
/// This is used to prevent multiple tooltips to cover each other.
/// Reset at the start of each frame.
pub tooltip_state: TooltipFrameState,

/// The current scroll area should scroll to this range (horizontal, vertical).
Expand Down
16 changes: 16 additions & 0 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,22 @@ impl Response {
}
}

let is_other_tooltip_open = self.ctx.prev_frame_state(|fs| {
if let Some(already_open_tooltip) = fs
.tooltip_state
.per_layer_tooltip_widget
.get(&self.layer_id)
{
already_open_tooltip != &self.id
} else {
false
}
});
if is_other_tooltip_open {
// We only allow one tooltip per layer. First one wins. It is up to that tooltip to close itself.
return false;
}

// Fast early-outs:
if self.enabled {
if !self.hovered || !self.ctx.input(|i| i.pointer.has_pointer()) {
Expand Down

0 comments on commit 9fb9887

Please sign in to comment.