From a650c146f14e17b9f151a89a6a222aba036e5f7e Mon Sep 17 00:00:00 2001 From: K Simmons Date: Fri, 22 Jul 2022 14:00:38 -0700 Subject: [PATCH] more event wip --- .../gpui/src/elements/mouse_event_handler.rs | 27 ++++ crates/gpui/src/presenter.rs | 147 ++++++++---------- crates/gpui/src/scene/mouse_region.rs | 92 +++++++++-- crates/workspace/src/pane.rs | 6 +- 4 files changed, 175 insertions(+), 97 deletions(-) diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 7ad43c47de..35e8d6407e 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -51,6 +51,15 @@ impl MouseEventHandler { self } + pub fn on_up( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_up(button, handler); + self + } + pub fn on_click( mut self, button: MouseButton, @@ -69,6 +78,15 @@ impl MouseEventHandler { self } + pub fn on_up_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_up(button, handler); + self + } + pub fn on_drag( mut self, button: MouseButton, @@ -78,6 +96,15 @@ impl MouseEventHandler { self } + pub fn on_drag_over( + mut self, + button: MouseButton, + handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_drag_over(button, handler); + self + } + pub fn on_hover( mut self, handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 023e013d13..deb6e5ed91 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -234,10 +234,7 @@ impl Presenter { pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) -> bool { if let Some(root_view_id) = cx.root_view_id(self.window_id) { let mut invalidated_views = Vec::new(); - let mut mouse_down_out_handlers = Vec::new(); - let mut mouse_down_region = None; - let mut clicked_region = None; - let mut dragged_region = None; + let mut events_to_send = Vec::new(); match &event { Event::MouseDown( @@ -248,32 +245,42 @@ impl Presenter { let mut hit = false; for (region, _) in self.mouse_regions.iter().rev() { if region.bounds.contains_point(*position) { - if !hit { - hit = true; + if !std::mem::replace(&mut hit, true) { invalidated_views.push(region.view_id); - mouse_down_region = - Some((region.clone(), MouseRegionEvent::Down(e.clone()))); + events_to_send + .push((region.clone(), MouseRegionEvent::Down(e.clone()))); self.clicked_region = Some(region.clone()); self.prev_drag_position = Some(*position); } - } else if let Some(handler) = region - .handlers - .get(&(MouseRegionEvent::down_out_disc(), Some(*button))) - { - mouse_down_out_handlers.push(( - handler, - region.view_id, - MouseRegionEvent::DownOut(e.clone()), - )); + } else { + events_to_send + .push((region.clone(), MouseRegionEvent::DownOut(e.clone()))); } } } - Event::MouseUp(e @ MouseButtonEvent { position, .. }) => { + Event::MouseUp( + e @ MouseButtonEvent { + position, button, .. + }, + ) => { + let mut hit = false; + for (region, _) in self.mouse_regions.iter().rev() { + if region.bounds.contains_point(*position) { + if !std::mem::replace(&mut hit, true) { + invalidated_views.push(region.view_id); + events_to_send + .push((region.clone(), MouseRegionEvent::Up(e.clone()))); + } + } else { + events_to_send + .push((region.clone(), MouseRegionEvent::UpOut(e.clone()))); + } + } self.prev_drag_position.take(); if let Some(region) = self.clicked_region.take() { invalidated_views.push(region.view_id); if region.bounds.contains_point(*position) { - clicked_region = Some((region, MouseRegionEvent::Click(e.clone()))); + events_to_send.push((region, MouseRegionEvent::Click(e.clone()))); } } } @@ -283,7 +290,7 @@ impl Presenter { .as_ref() .zip(self.prev_drag_position.as_mut()) { - dragged_region = Some(( + events_to_send.push(( clicked_region.clone(), MouseRegionEvent::Drag(*prev_drag_position, *e), )); @@ -298,39 +305,11 @@ impl Presenter { let (mut handled, mut event_cx) = self.handle_hover_events(&event, &mut invalidated_views, cx); - for (handler, view_id, region_event) in mouse_down_out_handlers { - event_cx.with_current_view(view_id, |event_cx| handler(region_event, event_cx)) - } - - if let Some((mouse_down_region, region_event)) = mouse_down_region { + for (region, event) in events_to_send { handled = true; - if let Some(mouse_down_callback) = - mouse_down_region.handlers.get(®ion_event.handler_key()) - { - event_cx.with_current_view(mouse_down_region.view_id, |event_cx| { - mouse_down_callback(region_event, event_cx); - }) - } - } - - if let Some((clicked_region, region_event)) = clicked_region { - handled = true; - if let Some(click_callback) = - clicked_region.handlers.get(®ion_event.handler_key()) - { - event_cx.with_current_view(clicked_region.view_id, |event_cx| { - click_callback(region_event, event_cx); - }) - } - } - - if let Some((dragged_region, region_event)) = dragged_region { - handled = true; - if let Some(drag_callback) = - dragged_region.handlers.get(®ion_event.handler_key()) - { - event_cx.with_current_view(dragged_region.view_id, |event_cx| { - drag_callback(region_event, event_cx); + if let Some(callback) = region.handlers.get(&event.handler_key()) { + event_cx.with_current_view(region.view_id, |event_cx| { + callback(event, event_cx); }) } } @@ -366,38 +345,44 @@ impl Presenter { }, ) = event { - if pressed_button.is_none() { - let mut style_to_assign = CursorStyle::Arrow; - for region in self.cursor_regions.iter().rev() { - if region.bounds.contains_point(*position) { - style_to_assign = region.style; - break; - } + let mut style_to_assign = CursorStyle::Arrow; + for region in self.cursor_regions.iter().rev() { + if region.bounds.contains_point(*position) { + style_to_assign = region.style; + break; } - cx.platform().set_cursor_style(style_to_assign); + } + cx.platform().set_cursor_style(style_to_assign); - let mut hover_depth = None; - for (region, depth) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(*position) - && hover_depth.map_or(true, |hover_depth| hover_depth == *depth) - { - hover_depth = Some(*depth); - if let Some(region_id) = region.id() { - if !self.hovered_region_ids.contains(®ion_id) { - invalidated_views.push(region.view_id); - hover_regions - .push((region.clone(), MouseRegionEvent::Hover(true, *e))); - self.hovered_region_ids.insert(region_id); - } - } - } else if let Some(region_id) = region.id() { - if self.hovered_region_ids.contains(®ion_id) { + let mut hover_depth = None; + for (region, depth) in self.mouse_regions.iter().rev() { + if region.bounds.contains_point(*position) + && hover_depth.map_or(true, |hover_depth| hover_depth == *depth) + { + hover_depth = Some(*depth); + if let Some(region_id) = region.id() { + if !self.hovered_region_ids.contains(®ion_id) { invalidated_views.push(region.view_id); - hover_regions - .push((region.clone(), MouseRegionEvent::Hover(false, *e))); - self.hovered_region_ids.remove(®ion_id); + let region_event = if let Some(pressed_button) = pressed_button { + MouseRegionEvent::DragOver(true, e.clone()) + } else { + MouseRegionEvent::Hover(true, e.clone()) + }; + hover_regions.push((region.clone(), region_event)); + self.hovered_region_ids.insert(region_id); } } + } else if let Some(region_id) = region.id() { + if self.hovered_region_ids.contains(®ion_id) { + invalidated_views.push(region.view_id); + let region_event = if let Some(pressed_button) = pressed_button { + MouseRegionEvent::DragOver(false, e.clone()) + } else { + MouseRegionEvent::Hover(false, e.clone()) + }; + hover_regions.push((region.clone(), region_event)); + self.hovered_region_ids.remove(®ion_id); + } } } } @@ -407,9 +392,9 @@ impl Presenter { for (hover_region, region_event) in hover_regions { handled = true; - if let Some(hover_callback) = hover_region.handlers.get(®ion_event.handler_key()) { + if let Some(callback) = hover_region.handlers.get(®ion_event.handler_key()) { event_cx.with_current_view(hover_region.view_id, |event_cx| { - hover_callback(region_event, event_cx); + callback(region_event, event_cx); }) } } diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index 01bb9fde69..33415bc990 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -1,4 +1,8 @@ -use std::{any::TypeId, mem::Discriminant, rc::Rc}; +use std::{ + any::TypeId, + mem::{discriminant, Discriminant}, + rc::Rc, +}; use collections::HashMap; use pathfinder_geometry::{rect::RectF, vector::Vector2F}; @@ -81,6 +85,15 @@ impl MouseRegion { self } + pub fn on_up_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_up_out(button, handler); + self + } + pub fn on_drag( mut self, button: MouseButton, @@ -90,6 +103,15 @@ impl MouseRegion { self } + pub fn on_drag_over( + mut self, + button: MouseButton, + handler: impl Fn(Vector2F, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_drag_over(button, handler); + self + } + pub fn on_hover( mut self, handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, @@ -129,6 +151,10 @@ impl HandlerSet { (MouseRegionEvent::drag_disc(), Some(button)), Rc::new(|_, _| {}), ); + set.insert( + (MouseRegionEvent::drag_over_disc(), Some(button)), + Rc::new(|_, _| {}), + ); set.insert( (MouseRegionEvent::down_disc(), Some(button)), Rc::new(|_, _| {}), @@ -145,6 +171,10 @@ impl HandlerSet { (MouseRegionEvent::down_out_disc(), Some(button)), Rc::new(|_, _| {}), ); + set.insert( + (MouseRegionEvent::up_out_disc(), Some(button)), + Rc::new(|_, _| {}), + ); } set.insert( (MouseRegionEvent::scroll_wheel_disc(), None), @@ -233,6 +263,24 @@ impl HandlerSet { self } + pub fn on_up_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::up_out_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::UpOut(mouse_button_event) = region_event { + handler(mouse_button_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::UpOut, found {:?}", + region_event); + } + })); + self + } + pub fn on_drag( mut self, button: MouseButton, @@ -251,14 +299,32 @@ impl HandlerSet { self } + pub fn on_drag_over( + mut self, + button: MouseButton, + handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::drag_over_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::DragOver(started, mouse_moved_event) = region_event { + handler(started, mouse_moved_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DragOver, found {:?}", + region_event); + } + })); + self + } + pub fn on_hover( mut self, handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, ) -> Self { self.set.insert((MouseRegionEvent::hover_disc(), None), Rc::new(move |region_event, cx| { - if let MouseRegionEvent::Hover(hover, mouse_moved_event) = region_event { - handler(hover, mouse_moved_event, cx); + if let MouseRegionEvent::Hover(started, mouse_moved_event) = region_event { + handler(started, mouse_moved_event, cx); } else { panic!( "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Hover, found {:?}", @@ -273,7 +339,7 @@ impl HandlerSet { pub enum MouseRegionEvent { Move(MouseMovedEvent), Drag(Vector2F, MouseMovedEvent), - DragOver(Vector2F, MouseMovedEvent), + DragOver(bool, MouseMovedEvent), Hover(bool, MouseMovedEvent), Down(MouseButtonEvent), Up(MouseButtonEvent), @@ -285,40 +351,40 @@ pub enum MouseRegionEvent { impl MouseRegionEvent { pub fn move_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Move(Default::default())) + discriminant(&MouseRegionEvent::Move(Default::default())) } pub fn drag_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Drag( + discriminant(&MouseRegionEvent::Drag( Default::default(), Default::default(), )) } pub fn drag_over_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::DragOver( + discriminant(&MouseRegionEvent::DragOver( Default::default(), Default::default(), )) } pub fn hover_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Hover( + discriminant(&MouseRegionEvent::Hover( Default::default(), Default::default(), )) } pub fn down_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Down(Default::default())) + discriminant(&MouseRegionEvent::Down(Default::default())) } pub fn up_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Up(Default::default())) + discriminant(&MouseRegionEvent::Up(Default::default())) } pub fn up_out_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::UpOut(Default::default())) + discriminant(&MouseRegionEvent::UpOut(Default::default())) } pub fn click_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Click(Default::default())) + discriminant(&MouseRegionEvent::Click(Default::default())) } pub fn down_out_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::DownOut(Default::default())) + discriminant(&MouseRegionEvent::DownOut(Default::default())) } pub fn scroll_wheel_disc() -> Discriminant { std::mem::discriminant(&MouseRegionEvent::ScrollWheel(Default::default())) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index eb21c2ac83..2f58f7cba4 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1025,13 +1025,13 @@ impl Pane { .on_drag(MouseButton::Left, |_, cx| { cx.global::().dragging(some view handle) }) - .on_mouse_up_out(MouseButton::Left, |_, cx| { + .on_up_out(MouseButton::Left, |_, cx| { cx.global::().stopped_dragging(some view handle) }) - .on_drag_over(MouseButton::Left, |started, _, cx| { + .on_drag_over(MouseButton::Left, |started, _, _, cx| { if started { if let Some(tab) = cx.global::().current_dragged::() { - cx.dispatch_action(ReceivingTab) + cx.dispatch_action(ReceivingTab); } } })