gpui2: Add on_hover events

This commit is contained in:
Conrad Irwin 2023-11-03 12:51:38 -06:00
parent d73c54f604
commit 26e64fb843
2 changed files with 64 additions and 0 deletions

View file

@ -333,6 +333,37 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
}));
self
}
fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext<V>)) -> Self
where
Self: Sized,
{
debug_assert!(
self.stateful_interaction().hover_listener.is_none(),
"calling on_hover more than once on the same element is not supported"
);
self.stateful_interaction().hover_listener = Some(Box::new(listener));
self
}
fn tooltip<W>(
mut self,
build_tooltip: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + 'static,
) -> Self
where
Self: Sized,
W: 'static + Render,
{
debug_assert!(
self.stateful_interaction().tooltip_builder.is_none(),
"calling tooltip more than once on the same element is not supported"
);
self.stateful_interaction().tooltip_builder = Some(Box::new(move |view_state, cx| {
build_tooltip(view_state, cx).into()
}));
self
}
}
pub trait ElementInteraction<V: 'static>: 'static {
@ -568,6 +599,24 @@ pub trait ElementInteraction<V: 'static>: 'static {
}
}
if let Some(hover_listener) = stateful.hover_listener.take() {
let was_hovered = element_state.hover_state.clone();
let has_mouse_down = element_state.pending_mouse_down.lock().is_some();
cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| {
if phase != DispatchPhase::Bubble {
return;
}
let is_hovered = bounds.contains_point(&event.position) && !has_mouse_down;
let mut was_hovered = was_hovered.lock();
if is_hovered != was_hovered.clone() {
*was_hovered = is_hovered;
drop(was_hovered);
hover_listener(view_state, is_hovered, cx);
}
});
}
let active_state = element_state.active_state.clone();
if active_state.lock().is_none() {
let active_group_bounds = stateful
@ -639,6 +688,8 @@ pub struct StatefulInteraction<V> {
active_style: StyleRefinement,
group_active_style: Option<GroupStyle>,
drag_listener: Option<DragListener<V>>,
hover_listener: Option<HoverListener<V>>,
tooltip_builder: Option<TooltipBuilder<V>>,
}
impl<V: 'static> ElementInteraction<V> for StatefulInteraction<V> {
@ -666,6 +717,8 @@ impl<V> From<ElementId> for StatefulInteraction<V> {
stateless: StatelessInteraction::default(),
click_listeners: SmallVec::new(),
drag_listener: None,
hover_listener: None,
tooltip_builder: None,
active_style: StyleRefinement::default(),
group_active_style: None,
}
@ -695,6 +748,8 @@ impl<V> StatelessInteraction<V> {
stateless: self,
click_listeners: SmallVec::new(),
drag_listener: None,
hover_listener: None,
tooltip_builder: None,
active_style: StyleRefinement::default(),
group_active_style: None,
}
@ -746,6 +801,7 @@ impl ActiveState {
#[derive(Default)]
pub struct InteractiveElementState {
active_state: Arc<Mutex<ActiveState>>,
hover_state: Arc<Mutex<bool>>,
pending_mouse_down: Arc<Mutex<Option<MouseDownEvent>>>,
scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
}
@ -1097,6 +1153,10 @@ pub type ClickListener<V> = Box<dyn Fn(&mut V, &ClickEvent, &mut ViewContext<V>)
pub(crate) type DragListener<V> =
Box<dyn Fn(&mut V, Point<Pixels>, &mut ViewContext<V>) -> AnyDrag + 'static>;
pub(crate) type HoverListener<V> = Box<dyn Fn(&mut V, bool, &mut ViewContext<V>) + 'static>;
pub(crate) type TooltipBuilder<V> = Box<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static>;
pub type KeyListener<V> = Box<
dyn Fn(
&mut V,

View file

@ -1399,6 +1399,10 @@ impl Pane {
.group("")
.id(item.id())
.cursor_pointer()
.on_hover(|_, hovered, _| {
dbg!(hovered);
})
// .tooltip(|pane, cx| cx.create_view( tooltip.child("Hovering the tab"))
// .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx))
// .drag_over::<DraggedTab>(|d| d.bg(cx.theme().colors().element_drop_target))
// .on_drop(|_view, state: View<DraggedTab>, cx| {