MOAR TOOLTIPS

Conrad Irwin created

Change summary

crates/gpui2/src/interactive.rs | 51 ++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 16 deletions(-)

Detailed changes

crates/gpui2/src/interactive.rs 🔗

@@ -17,6 +17,7 @@ use std::{
     ops::Deref,
     path::PathBuf,
     sync::Arc,
+    time::{Duration, Instant},
 };
 
 const DRAG_THRESHOLD: f64 = 2.;
@@ -603,9 +604,6 @@ pub trait ElementInteraction<V: 'static>: 'static {
                 let was_hovered = element_state.hover_state.clone();
                 let has_mouse_down = element_state.pending_mouse_down.lock().is_some();
 
-                let active_tooltip = element_state.active_tooltip.clone();
-                let tooltip_builder = stateful.tooltip_builder.clone();
-
                 cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
                     if phase != DispatchPhase::Bubble {
                         return;
@@ -616,23 +614,39 @@ pub trait ElementInteraction<V: 'static>: 'static {
                     if is_hovered != was_hovered.clone() {
                         *was_hovered = is_hovered;
                         drop(was_hovered);
-                        if let Some(tooltip_builder) = &tooltip_builder {
-                            let mut active_tooltip = active_tooltip.lock();
-                            if is_hovered && active_tooltip.is_none() {
-                                *active_tooltip = Some(tooltip_builder(view_state, cx));
-                            } else if !is_hovered {
-                                active_tooltip.take();
-                            }
-                        }
 
                         hover_listener(view_state, is_hovered, cx);
                     }
                 });
             }
 
-            if let Some(active_tooltip) = element_state.active_tooltip.lock().as_ref() {
-                if *element_state.hover_state.lock() {
-                    cx.active_tooltip = Some(active_tooltip.clone());
+            // if we're hovered:
+            //   if no timer, start timer
+            //   if timer hits 1s, call tooltip_builder()
+            //
+
+            if let Some(tooltip_builder) = &stateful.tooltip_builder {
+                let mut active_tooltip = element_state.active_tooltip.lock();
+                let is_hovered = bounds.contains_point(&cx.mouse_position())
+                    && !element_state.pending_mouse_down.lock().is_some();
+
+                if is_hovered {
+                    if let Some(active_tooltip) = active_tooltip {
+                        active_tooltip.view = Some(tooltip_builder(cx))
+                    } else {
+                        *active_tooltip = Some(ActiveTooltip {
+                            hover_start: Instant::now(),
+                            view: None,
+                        });
+                    }
+                } else {
+                    active_tooltip.take();
+                }
+
+                if let Some(active_tooltip) = element_state.active_tooltip.lock().as_ref() {
+                    if *element_state.hover_state.lock() {
+                        cx.active_tooltip = Some(active_tooltip.clone());
+                    }
                 }
             }
 
@@ -823,7 +837,12 @@ pub struct InteractiveElementState {
     hover_state: Arc<Mutex<bool>>,
     pending_mouse_down: Arc<Mutex<Option<MouseDownEvent>>>,
     scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
-    active_tooltip: Arc<Mutex<Option<AnyView>>>,
+    active_tooltip: Arc<Mutex<Option<ActiveTooltip>>>,
+}
+
+pub struct ActiveTooltip {
+    hover_start: Instant,
+    view: Option<AnyView>,
 }
 
 impl InteractiveElementState {
@@ -1175,7 +1194,7 @@ pub(crate) type DragListener<V> =
 
 pub(crate) type HoverListener<V> = Box<dyn Fn(&mut V, bool, &mut ViewContext<V>) + 'static>;
 
-pub(crate) type TooltipBuilder<V> = Arc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static>;
+pub(crate) type TooltipBuilder<V> = Arc<dyn Fn(&mut ViewContext<V>) -> AnyView + 'static>;
 
 pub type KeyListener<V> = Box<
     dyn Fn(