Make sure all tooltips close if you open a menu in the same layer (#4766)
This commit is contained in:
parent
d1be5a1efb
commit
249b69d534
|
|
@ -6,6 +6,29 @@ use crate::*;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn when_was_a_toolip_last_shown_id() -> Id {
|
||||||
|
Id::new("when_was_a_toolip_last_shown")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seconds_since_last_tooltip(ctx: &Context) -> f32 {
|
||||||
|
let when_was_a_toolip_last_shown =
|
||||||
|
ctx.data(|d| d.get_temp::<f64>(when_was_a_toolip_last_shown_id()));
|
||||||
|
|
||||||
|
if let Some(when_was_a_toolip_last_shown) = when_was_a_toolip_last_shown {
|
||||||
|
let now = ctx.input(|i| i.time);
|
||||||
|
(now - when_was_a_toolip_last_shown) as f32
|
||||||
|
} else {
|
||||||
|
f32::INFINITY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remember_that_tooltip_was_shown(ctx: &Context) {
|
||||||
|
let now = ctx.input(|i| i.time);
|
||||||
|
ctx.data_mut(|data| data.insert_temp::<f64>(when_was_a_toolip_last_shown_id(), now));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Show a tooltip at the current pointer position (if any).
|
/// Show a tooltip at the current pointer position (if any).
|
||||||
///
|
///
|
||||||
/// Most of the time it is easier to use [`Response::on_hover_ui`].
|
/// Most of the time it is easier to use [`Response::on_hover_ui`].
|
||||||
|
|
@ -123,14 +146,16 @@ fn show_tooltip_at_dyn<'c, R>(
|
||||||
widget_rect = transform * widget_rect;
|
widget_rect = transform * widget_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there are multiple tooltips open they should use the same common_id for the `tooltip_size` caching to work.
|
remember_that_tooltip_was_shown(ctx);
|
||||||
|
|
||||||
let mut state = ctx.frame_state_mut(|fs| {
|
let mut state = ctx.frame_state_mut(|fs| {
|
||||||
// Remember that this is the widget showing the tooltip:
|
// Remember that this is the widget showing the tooltip:
|
||||||
fs.tooltip_state
|
fs.layers
|
||||||
.per_layer_tooltip_widget
|
.entry(parent_layer)
|
||||||
.insert(parent_layer, widget_id);
|
.or_default()
|
||||||
|
.widget_with_tooltip = Some(widget_id);
|
||||||
|
|
||||||
fs.tooltip_state
|
fs.tooltips
|
||||||
.widget_tooltips
|
.widget_tooltips
|
||||||
.get(&widget_id)
|
.get(&widget_id)
|
||||||
.copied()
|
.copied()
|
||||||
|
|
@ -174,7 +199,7 @@ fn show_tooltip_at_dyn<'c, R>(
|
||||||
|
|
||||||
state.tooltip_count += 1;
|
state.tooltip_count += 1;
|
||||||
state.bounding_rect = state.bounding_rect.union(response.rect);
|
state.bounding_rect = state.bounding_rect.union(response.rect);
|
||||||
ctx.frame_state_mut(|fs| fs.tooltip_state.widget_tooltips.insert(widget_id, state));
|
ctx.frame_state_mut(|fs| fs.tooltips.widget_tooltips.insert(widget_id, state));
|
||||||
|
|
||||||
inner
|
inner
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +207,7 @@ fn show_tooltip_at_dyn<'c, R>(
|
||||||
/// What is the id of the next tooltip for this widget?
|
/// What is the id of the next tooltip for this widget?
|
||||||
pub fn next_tooltip_id(ctx: &Context, widget_id: Id) -> Id {
|
pub fn next_tooltip_id(ctx: &Context, widget_id: Id) -> Id {
|
||||||
let tooltip_count = ctx.frame_state(|fs| {
|
let tooltip_count = ctx.frame_state(|fs| {
|
||||||
fs.tooltip_state
|
fs.tooltips
|
||||||
.widget_tooltips
|
.widget_tooltips
|
||||||
.get(&widget_id)
|
.get(&widget_id)
|
||||||
.map_or(0, |state| state.tooltip_count)
|
.map_or(0, |state| state.tooltip_count)
|
||||||
|
|
@ -351,53 +376,61 @@ pub fn popup_above_or_below_widget<R>(
|
||||||
close_behavior: PopupCloseBehavior,
|
close_behavior: PopupCloseBehavior,
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> Option<R> {
|
) -> Option<R> {
|
||||||
if parent_ui.memory(|mem| mem.is_popup_open(popup_id)) {
|
if !parent_ui.memory(|mem| mem.is_popup_open(popup_id)) {
|
||||||
let (mut pos, pivot) = match above_or_below {
|
return None;
|
||||||
AboveOrBelow::Above => (widget_response.rect.left_top(), Align2::LEFT_BOTTOM),
|
}
|
||||||
AboveOrBelow::Below => (widget_response.rect.left_bottom(), Align2::LEFT_TOP),
|
|
||||||
};
|
|
||||||
if let Some(transform) = parent_ui
|
|
||||||
.ctx()
|
|
||||||
.memory(|m| m.layer_transforms.get(&parent_ui.layer_id()).copied())
|
|
||||||
{
|
|
||||||
pos = transform * pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
let frame = Frame::popup(parent_ui.style());
|
let (mut pos, pivot) = match above_or_below {
|
||||||
let frame_margin = frame.total_margin();
|
AboveOrBelow::Above => (widget_response.rect.left_top(), Align2::LEFT_BOTTOM),
|
||||||
let inner_width = widget_response.rect.width() - frame_margin.sum().x;
|
AboveOrBelow::Below => (widget_response.rect.left_bottom(), Align2::LEFT_TOP),
|
||||||
|
};
|
||||||
|
if let Some(transform) = parent_ui
|
||||||
|
.ctx()
|
||||||
|
.memory(|m| m.layer_transforms.get(&parent_ui.layer_id()).copied())
|
||||||
|
{
|
||||||
|
pos = transform * pos;
|
||||||
|
}
|
||||||
|
|
||||||
let response = Area::new(popup_id)
|
let frame = Frame::popup(parent_ui.style());
|
||||||
.kind(UiKind::Popup)
|
let frame_margin = frame.total_margin();
|
||||||
.order(Order::Foreground)
|
let inner_width = widget_response.rect.width() - frame_margin.sum().x;
|
||||||
.fixed_pos(pos)
|
|
||||||
.default_width(inner_width)
|
parent_ui.ctx().frame_state_mut(|fs| {
|
||||||
.pivot(pivot)
|
fs.layers
|
||||||
.show(parent_ui.ctx(), |ui| {
|
.entry(parent_ui.layer_id())
|
||||||
frame
|
.or_default()
|
||||||
.show(ui, |ui| {
|
.open_popups
|
||||||
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
|
.insert(popup_id)
|
||||||
ui.set_min_width(inner_width);
|
});
|
||||||
add_contents(ui)
|
|
||||||
})
|
let response = Area::new(popup_id)
|
||||||
.inner
|
.kind(UiKind::Popup)
|
||||||
|
.order(Order::Foreground)
|
||||||
|
.fixed_pos(pos)
|
||||||
|
.default_width(inner_width)
|
||||||
|
.pivot(pivot)
|
||||||
|
.show(parent_ui.ctx(), |ui| {
|
||||||
|
frame
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
|
||||||
|
ui.set_min_width(inner_width);
|
||||||
|
add_contents(ui)
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
});
|
})
|
||||||
|
.inner
|
||||||
|
});
|
||||||
|
|
||||||
let should_close = match close_behavior {
|
let should_close = match close_behavior {
|
||||||
PopupCloseBehavior::CloseOnClick => widget_response.clicked_elsewhere(),
|
PopupCloseBehavior::CloseOnClick => widget_response.clicked_elsewhere(),
|
||||||
PopupCloseBehavior::CloseOnClickOutside => {
|
PopupCloseBehavior::CloseOnClickOutside => {
|
||||||
widget_response.clicked_elsewhere() && response.response.clicked_elsewhere()
|
widget_response.clicked_elsewhere() && response.response.clicked_elsewhere()
|
||||||
}
|
|
||||||
PopupCloseBehavior::IgnoreClicks => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if parent_ui.input(|i| i.key_pressed(Key::Escape)) || should_close {
|
|
||||||
parent_ui.memory_mut(|mem| mem.close_popup());
|
|
||||||
}
|
}
|
||||||
Some(response.inner)
|
PopupCloseBehavior::IgnoreClicks => false,
|
||||||
} else {
|
};
|
||||||
None
|
|
||||||
|
if parent_ui.input(|i| i.key_pressed(Key::Escape)) || should_close {
|
||||||
|
parent_ui.memory_mut(|mem| mem.close_popup());
|
||||||
}
|
}
|
||||||
|
Some(response.inner)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use ahash::{HashMap, HashSet};
|
||||||
|
|
||||||
use crate::{id::IdSet, *};
|
use crate::{id::IdSet, *};
|
||||||
|
|
||||||
/// Reset at the start of each frame.
|
/// Reset at the start of each frame.
|
||||||
|
|
@ -6,22 +8,12 @@ pub struct TooltipFrameState {
|
||||||
/// If a tooltip has been shown this frame, where was it?
|
/// If a tooltip has been shown this frame, where was it?
|
||||||
/// This is used to prevent multiple tooltips to cover each other.
|
/// This is used to prevent multiple tooltips to cover each other.
|
||||||
pub widget_tooltips: IdMap<PerWidgetTooltipState>,
|
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 {
|
impl TooltipFrameState {
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
let Self {
|
let Self { widget_tooltips } = self;
|
||||||
widget_tooltips,
|
|
||||||
per_layer_tooltip_widget,
|
|
||||||
} = self;
|
|
||||||
widget_tooltips.clear();
|
widget_tooltips.clear();
|
||||||
per_layer_tooltip_widget.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,6 +26,20 @@ pub struct PerWidgetTooltipState {
|
||||||
pub tooltip_count: usize,
|
pub tooltip_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct PerLayerState {
|
||||||
|
/// Is there any open popup (menus, combo-boxes, etc)?
|
||||||
|
///
|
||||||
|
/// Does NOT include tooltips.
|
||||||
|
pub open_popups: HashSet<Id>,
|
||||||
|
|
||||||
|
/// 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 widget_with_tooltip: Option<Id>,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AccessKitFrameState {
|
pub struct AccessKitFrameState {
|
||||||
|
|
@ -53,6 +59,13 @@ pub struct FrameState {
|
||||||
/// All widgets produced this frame.
|
/// All widgets produced this frame.
|
||||||
pub widgets: WidgetRects,
|
pub widgets: WidgetRects,
|
||||||
|
|
||||||
|
/// Per-layer state.
|
||||||
|
///
|
||||||
|
/// Not all layers registers themselves there though.
|
||||||
|
pub layers: HashMap<LayerId, PerLayerState>,
|
||||||
|
|
||||||
|
pub tooltips: TooltipFrameState,
|
||||||
|
|
||||||
/// Starts off as the `screen_rect`, shrinks as panels are added.
|
/// Starts off as the `screen_rect`, shrinks as panels are added.
|
||||||
/// The [`CentralPanel`] does not change this.
|
/// The [`CentralPanel`] does not change this.
|
||||||
/// This is the area available to Window's.
|
/// This is the area available to Window's.
|
||||||
|
|
@ -65,8 +78,6 @@ pub struct FrameState {
|
||||||
/// How much space is used by panels.
|
/// How much space is used by panels.
|
||||||
pub used_by_panels: Rect,
|
pub used_by_panels: Rect,
|
||||||
|
|
||||||
pub tooltip_state: TooltipFrameState,
|
|
||||||
|
|
||||||
/// The current scroll area should scroll to this range (horizontal, vertical).
|
/// The current scroll area should scroll to this range (horizontal, vertical).
|
||||||
pub scroll_target: [Option<(Rangef, Option<Align>)>; 2],
|
pub scroll_target: [Option<(Rangef, Option<Align>)>; 2],
|
||||||
|
|
||||||
|
|
@ -96,10 +107,11 @@ impl Default for FrameState {
|
||||||
Self {
|
Self {
|
||||||
used_ids: Default::default(),
|
used_ids: Default::default(),
|
||||||
widgets: Default::default(),
|
widgets: Default::default(),
|
||||||
|
layers: Default::default(),
|
||||||
|
tooltips: Default::default(),
|
||||||
available_rect: Rect::NAN,
|
available_rect: Rect::NAN,
|
||||||
unused_rect: Rect::NAN,
|
unused_rect: Rect::NAN,
|
||||||
used_by_panels: Rect::NAN,
|
used_by_panels: Rect::NAN,
|
||||||
tooltip_state: Default::default(),
|
|
||||||
scroll_target: [None, None],
|
scroll_target: [None, None],
|
||||||
scroll_delta: Vec2::default(),
|
scroll_delta: Vec2::default(),
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
|
|
@ -118,10 +130,11 @@ impl FrameState {
|
||||||
let Self {
|
let Self {
|
||||||
used_ids,
|
used_ids,
|
||||||
widgets,
|
widgets,
|
||||||
|
tooltips,
|
||||||
|
layers,
|
||||||
available_rect,
|
available_rect,
|
||||||
unused_rect,
|
unused_rect,
|
||||||
used_by_panels,
|
used_by_panels,
|
||||||
tooltip_state,
|
|
||||||
scroll_target,
|
scroll_target,
|
||||||
scroll_delta,
|
scroll_delta,
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
|
|
@ -134,10 +147,11 @@ impl FrameState {
|
||||||
|
|
||||||
used_ids.clear();
|
used_ids.clear();
|
||||||
widgets.clear();
|
widgets.clear();
|
||||||
|
tooltips.clear();
|
||||||
|
layers.clear();
|
||||||
*available_rect = screen_rect;
|
*available_rect = screen_rect;
|
||||||
*unused_rect = screen_rect;
|
*unused_rect = screen_rect;
|
||||||
*used_by_panels = Rect::NOTHING;
|
*used_by_panels = Rect::NOTHING;
|
||||||
tooltip_state.clear();
|
|
||||||
*scroll_target = [None, None];
|
*scroll_target = [None, None];
|
||||||
*scroll_delta = Vec2::default();
|
*scroll_delta = Vec2::default();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ pub(crate) fn submenu_button<R>(
|
||||||
/// wrapper for the contents of every menu.
|
/// wrapper for the contents of every menu.
|
||||||
fn menu_popup<'c, R>(
|
fn menu_popup<'c, R>(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
|
parent_layer: LayerId,
|
||||||
menu_state_arc: &Arc<RwLock<MenuState>>,
|
menu_state_arc: &Arc<RwLock<MenuState>>,
|
||||||
menu_id: Id,
|
menu_id: Id,
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R + 'c,
|
add_contents: impl FnOnce(&mut Ui) -> R + 'c,
|
||||||
|
|
@ -145,7 +146,17 @@ fn menu_popup<'c, R>(
|
||||||
menu_state.rect.min
|
menu_state.rect.min
|
||||||
};
|
};
|
||||||
|
|
||||||
let area = Area::new(menu_id.with("__menu"))
|
let area_id = menu_id.with("__menu");
|
||||||
|
|
||||||
|
ctx.frame_state_mut(|fs| {
|
||||||
|
fs.layers
|
||||||
|
.entry(parent_layer)
|
||||||
|
.or_default()
|
||||||
|
.open_popups
|
||||||
|
.insert(area_id)
|
||||||
|
});
|
||||||
|
|
||||||
|
let area = Area::new(area_id)
|
||||||
.kind(UiKind::Menu)
|
.kind(UiKind::Menu)
|
||||||
.order(Order::Foreground)
|
.order(Order::Foreground)
|
||||||
.fixed_pos(pos)
|
.fixed_pos(pos)
|
||||||
|
|
@ -320,7 +331,13 @@ impl MenuRoot {
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> (MenuResponse, Option<InnerResponse<R>>) {
|
) -> (MenuResponse, Option<InnerResponse<R>>) {
|
||||||
if self.id == button.id {
|
if self.id == button.id {
|
||||||
let inner_response = menu_popup(&button.ctx, &self.menu_state, self.id, add_contents);
|
let inner_response = menu_popup(
|
||||||
|
&button.ctx,
|
||||||
|
button.layer_id,
|
||||||
|
&self.menu_state,
|
||||||
|
self.id,
|
||||||
|
add_contents,
|
||||||
|
);
|
||||||
let menu_state = self.menu_state.read();
|
let menu_state = self.menu_state.read();
|
||||||
|
|
||||||
let escape_pressed = button.ctx.input(|i| i.key_pressed(Key::Escape));
|
let escape_pressed = button.ctx.input(|i| i.key_pressed(Key::Escape));
|
||||||
|
|
@ -580,10 +597,10 @@ impl SubMenu {
|
||||||
self.parent_state
|
self.parent_state
|
||||||
.write()
|
.write()
|
||||||
.submenu_button_interaction(ui, sub_id, &response);
|
.submenu_button_interaction(ui, sub_id, &response);
|
||||||
let inner = self
|
let inner =
|
||||||
.parent_state
|
self.parent_state
|
||||||
.write()
|
.write()
|
||||||
.show_submenu(ui.ctx(), sub_id, add_contents);
|
.show_submenu(ui.ctx(), ui.layer_id(), sub_id, add_contents);
|
||||||
InnerResponse::new(inner, response)
|
InnerResponse::new(inner, response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -624,11 +641,12 @@ impl MenuState {
|
||||||
fn show_submenu<R>(
|
fn show_submenu<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
|
parent_layer: LayerId,
|
||||||
id: Id,
|
id: Id,
|
||||||
add_contents: impl FnOnce(&mut Ui) -> R,
|
add_contents: impl FnOnce(&mut Ui) -> R,
|
||||||
) -> Option<R> {
|
) -> Option<R> {
|
||||||
let (sub_response, response) = self.submenu(id).map(|sub| {
|
let (sub_response, response) = self.submenu(id).map(|sub| {
|
||||||
let inner_response = menu_popup(ctx, sub, id, add_contents);
|
let inner_response = menu_popup(ctx, parent_layer, sub, id, add_contents);
|
||||||
(sub.read().response, inner_response.inner)
|
(sub.read().response, inner_response.inner)
|
||||||
})?;
|
})?;
|
||||||
self.cascade_close_response(sub_response);
|
self.cascade_close_response(sub_response);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use std::{any::Any, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
emath::{Align, Pos2, Rect, Vec2},
|
emath::{Align, Pos2, Rect, Vec2},
|
||||||
menu, AreaState, ComboBox, Context, CursorIcon, Id, LayerId, Order, PointerButton, Sense, Ui,
|
menu, AreaState, Context, CursorIcon, Id, LayerId, Order, PointerButton, Sense, Ui, WidgetRect,
|
||||||
WidgetRect, WidgetText,
|
WidgetText,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -601,9 +601,19 @@ impl Response {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_tooltip_open = self.is_tooltip_open();
|
let any_open_popups = self.ctx.prev_frame_state(|fs| {
|
||||||
|
fs.layers
|
||||||
|
.get(&self.layer_id)
|
||||||
|
.map_or(false, |layer| !layer.open_popups.is_empty())
|
||||||
|
});
|
||||||
|
if any_open_popups {
|
||||||
|
// Hide tooltips if the user opens a popup (menu, combo-box, etc) in the same layer.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if is_tooltip_open {
|
let is_our_tooltip_open = self.is_tooltip_open();
|
||||||
|
|
||||||
|
if is_our_tooltip_open {
|
||||||
let (pointer_pos, pointer_dir) = self
|
let (pointer_pos, pointer_dir) = self
|
||||||
.ctx
|
.ctx
|
||||||
.input(|i| (i.pointer.hover_pos(), i.pointer.direction()));
|
.input(|i| (i.pointer.hover_pos(), i.pointer.direction()));
|
||||||
|
|
@ -647,11 +657,11 @@ impl Response {
|
||||||
|
|
||||||
let is_other_tooltip_open = self.ctx.prev_frame_state(|fs| {
|
let is_other_tooltip_open = self.ctx.prev_frame_state(|fs| {
|
||||||
if let Some(already_open_tooltip) = fs
|
if let Some(already_open_tooltip) = fs
|
||||||
.tooltip_state
|
.layers
|
||||||
.per_layer_tooltip_widget
|
|
||||||
.get(&self.layer_id)
|
.get(&self.layer_id)
|
||||||
|
.and_then(|layer| layer.widget_with_tooltip)
|
||||||
{
|
{
|
||||||
already_open_tooltip != &self.id
|
already_open_tooltip != self.id
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
@ -670,21 +680,6 @@ impl Response {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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_delay = self.ctx.style().interaction.tooltip_delay;
|
||||||
let tooltip_grace_time = self.ctx.style().interaction.tooltip_grace_time;
|
let tooltip_grace_time = self.ctx.style().interaction.tooltip_grace_time;
|
||||||
|
|
||||||
|
|
@ -693,10 +688,10 @@ impl Response {
|
||||||
// another widget should show the tooltip for that widget right away.
|
// 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 the user quickly move over some dead space to hover the next thing
|
||||||
let tooltip_was_recently_shown = when_was_a_toolip_last_shown
|
let tooltip_was_recently_shown =
|
||||||
.map_or(false, |time| ((now - time) as f32) < tooltip_grace_time);
|
crate::popup::seconds_since_last_tooltip(&self.ctx) < tooltip_grace_time;
|
||||||
|
|
||||||
if !tooltip_was_recently_shown && !is_tooltip_open {
|
if !tooltip_was_recently_shown && !is_our_tooltip_open {
|
||||||
if self.ctx.style().interaction.show_tooltips_only_when_still {
|
if self.ctx.style().interaction.show_tooltips_only_when_still {
|
||||||
// We only show the tooltip when the mouse pointer is still.
|
// We only show the tooltip when the mouse pointer is still.
|
||||||
if !self.ctx.input(|i| i.pointer.is_still()) {
|
if !self.ctx.input(|i| i.pointer.is_still()) {
|
||||||
|
|
@ -729,10 +724,6 @@ impl Response {
|
||||||
|
|
||||||
// All checks passed: show the tooltip!
|
// 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
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue