diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 243863149d..a2b3230190 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -252,7 +252,6 @@ impl Presenter { } else if let Some(handler) = region .handlers .get(&(MouseRegionEvent::down_out_disc(), Some(*button))) - .cloned() { mouse_down_out_handlers.push(( handler, diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index f5577c5e5d..a1f12b76d3 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -1,7 +1,8 @@ -use collections::HashMap; +mod mouse_region; + use serde::Deserialize; use serde_json::json; -use std::{any::TypeId, borrow::Cow, mem::Discriminant, rc::Rc, sync::Arc}; +use std::{borrow::Cow, sync::Arc}; use crate::{ color::Color, @@ -9,8 +10,9 @@ use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::ToJson, platform::CursorStyle, - EventContext, ImageData, MouseButton, MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent, + ImageData, }; +pub use mouse_region::*; pub struct Scene { scale_factor: f32, @@ -45,255 +47,6 @@ pub struct CursorRegion { pub style: CursorStyle, } -#[derive(Debug)] -pub enum MouseRegionEvent { - Move(MouseMovedEvent), - Drag(Vector2F, MouseMovedEvent), - Hover(bool, MouseMovedEvent), - Down(MouseButtonEvent), - Up(MouseButtonEvent), - Click(MouseButtonEvent), - DownOut(MouseButtonEvent), - ScrollWheel(ScrollWheelEvent), -} - -impl MouseRegionEvent { - pub fn move_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Move(Default::default())) - } - pub fn drag_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Drag( - Default::default(), - Default::default(), - )) - } - pub fn hover_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Hover( - Default::default(), - Default::default(), - )) - } - pub fn down_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Down(Default::default())) - } - pub fn up_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Up(Default::default())) - } - pub fn click_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::Click(Default::default())) - } - pub fn down_out_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::DownOut(Default::default())) - } - pub fn scroll_wheel_disc() -> Discriminant { - std::mem::discriminant(&MouseRegionEvent::ScrollWheel(Default::default())) - } - - pub fn handler_key(&self) -> (Discriminant, Option) { - match self { - MouseRegionEvent::Move(_) => (Self::move_disc(), None), - MouseRegionEvent::Drag(_, MouseMovedEvent { pressed_button, .. }) => { - (Self::drag_disc(), *pressed_button) - } - MouseRegionEvent::Hover(_, _) => (Self::hover_disc(), None), - MouseRegionEvent::Down(MouseButtonEvent { button, .. }) => { - (Self::down_disc(), Some(*button)) - } - MouseRegionEvent::Up(MouseButtonEvent { button, .. }) => { - (Self::up_disc(), Some(*button)) - } - MouseRegionEvent::Click(MouseButtonEvent { button, .. }) => { - (Self::click_disc(), Some(*button)) - } - MouseRegionEvent::DownOut(MouseButtonEvent { button, .. }) => { - (Self::down_out_disc(), Some(*button)) - } - MouseRegionEvent::ScrollWheel(_) => (Self::scroll_wheel_disc(), None), - } - } -} - -#[derive(Clone, Default)] -pub struct MouseRegion { - pub view_id: usize, - pub discriminant: Option<(TypeId, usize)>, - pub bounds: RectF, - pub handlers: HashMap< - (Discriminant, Option), - Rc, - >, -} - -impl MouseRegion { - pub fn new(view_id: usize, discriminant: Option<(TypeId, usize)>, bounds: RectF) -> Self { - Self { - view_id, - discriminant, - bounds, - handlers: Default::default(), - } - } - - pub fn handle_all( - view_id: usize, - discriminant: Option<(TypeId, usize)>, - bounds: RectF, - ) -> Self { - let mut handlers: HashMap< - (Discriminant, Option), - Rc, - > = Default::default(); - handlers.insert((MouseRegionEvent::move_disc(), None), Rc::new(|_, _| {})); - handlers.insert((MouseRegionEvent::hover_disc(), None), Rc::new(|_, _| {})); - for button in MouseButton::all() { - handlers.insert( - (MouseRegionEvent::drag_disc(), Some(button)), - Rc::new(|_, _| {}), - ); - handlers.insert( - (MouseRegionEvent::down_disc(), Some(button)), - Rc::new(|_, _| {}), - ); - handlers.insert( - (MouseRegionEvent::up_disc(), Some(button)), - Rc::new(|_, _| {}), - ); - handlers.insert( - (MouseRegionEvent::click_disc(), Some(button)), - Rc::new(|_, _| {}), - ); - handlers.insert( - (MouseRegionEvent::down_out_disc(), Some(button)), - Rc::new(|_, _| {}), - ); - } - handlers.insert( - (MouseRegionEvent::scroll_wheel_disc(), None), - Rc::new(|_, _| {}), - ); - - Self { - view_id, - discriminant, - bounds, - handlers, - } - } - - pub fn on_down( - mut self, - button: MouseButton, - handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.insert((MouseRegionEvent::down_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::Down(mouse_button_event) = region_event { - handler(mouse_button_event, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Down, found {:?}", - region_event); - } - })); - self - } - - pub fn on_up( - mut self, - button: MouseButton, - handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.insert((MouseRegionEvent::up_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::Up(mouse_button_event) = region_event { - handler(mouse_button_event, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Up, found {:?}", - region_event); - } - })); - self - } - - pub fn on_click( - mut self, - button: MouseButton, - handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.insert((MouseRegionEvent::click_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::Click(mouse_button_event) = region_event { - handler(mouse_button_event, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Click, found {:?}", - region_event); - } - })); - self - } - - pub fn on_down_out( - mut self, - button: MouseButton, - handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.insert((MouseRegionEvent::down_out_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::DownOut(mouse_button_event) = region_event { - handler(mouse_button_event, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DownOut, found {:?}", - region_event); - } - })); - self - } - - pub fn on_drag( - mut self, - button: MouseButton, - handler: impl Fn(Vector2F, MouseMovedEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.insert((MouseRegionEvent::drag_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::Drag(prev_drag_position, mouse_moved_event) = region_event { - handler(prev_drag_position, mouse_moved_event, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Drag, found {:?}", - region_event); - } - })); - self - } - - pub fn on_hover( - mut self, - handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers.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); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Hover, found {:?}", - region_event); - } - })); - self - } -} - -#[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct MouseRegionId { - pub view_id: usize, - pub discriminant: (TypeId, usize), -} - #[derive(Default, Debug)] pub struct Quad { pub bounds: RectF, diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs new file mode 100644 index 0000000000..3d680876c7 --- /dev/null +++ b/crates/gpui/src/scene/mouse_region.rs @@ -0,0 +1,327 @@ +use std::{any::TypeId, mem::Discriminant, rc::Rc}; + +use collections::HashMap; +use pathfinder_geometry::{rect::RectF, vector::Vector2F}; + +use crate::{EventContext, MouseButton, MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent}; + +#[derive(Clone, Default)] +pub struct MouseRegion { + pub view_id: usize, + pub discriminant: Option<(TypeId, usize)>, + pub bounds: RectF, + pub handlers: HandlerSet, +} + +impl MouseRegion { + pub fn new(view_id: usize, discriminant: Option<(TypeId, usize)>, bounds: RectF) -> Self { + Self { + view_id, + discriminant, + bounds, + handlers: Default::default(), + } + } + + pub fn handle_all( + view_id: usize, + discriminant: Option<(TypeId, usize)>, + bounds: RectF, + ) -> Self { + Self { + view_id, + discriminant, + bounds, + handlers: HandlerSet::handle_all(), + } + } + + pub fn on_down( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_down(button, handler); + 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, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_click(button, handler); + self + } + + pub fn on_down_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_down_out(button, handler); + self + } + + pub fn on_drag( + mut self, + button: MouseButton, + handler: impl Fn(Vector2F, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_drag(button, handler); + self + } + + pub fn on_hover( + mut self, + handler: impl Fn(bool, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.handlers = self.handlers.on_hover(handler); + self + } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct MouseRegionId { + pub view_id: usize, + pub discriminant: (TypeId, usize), +} + +#[derive(Clone, Default)] +pub struct HandlerSet { + pub set: HashMap< + (Discriminant, Option), + Rc, + >, +} + +impl HandlerSet { + pub fn handle_all() -> Self { + let mut set: HashMap< + (Discriminant, Option), + Rc, + > = Default::default(); + + set.insert((MouseRegionEvent::move_disc(), None), Rc::new(|_, _| {})); + set.insert((MouseRegionEvent::hover_disc(), None), Rc::new(|_, _| {})); + for button in MouseButton::all() { + set.insert( + (MouseRegionEvent::drag_disc(), Some(button)), + Rc::new(|_, _| {}), + ); + set.insert( + (MouseRegionEvent::down_disc(), Some(button)), + Rc::new(|_, _| {}), + ); + set.insert( + (MouseRegionEvent::up_disc(), Some(button)), + Rc::new(|_, _| {}), + ); + set.insert( + (MouseRegionEvent::click_disc(), Some(button)), + Rc::new(|_, _| {}), + ); + set.insert( + (MouseRegionEvent::down_out_disc(), Some(button)), + Rc::new(|_, _| {}), + ); + } + set.insert( + (MouseRegionEvent::scroll_wheel_disc(), None), + Rc::new(|_, _| {}), + ); + + HandlerSet { set } + } + + pub fn get( + &self, + key: &(Discriminant, Option), + ) -> Option> { + self.set.get(key).cloned() + } + + pub fn on_down( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::down_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::Down(mouse_button_event) = region_event { + handler(mouse_button_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Down, found {:?}", + region_event); + } + })); + self + } + + pub fn on_up( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::up_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::Up(mouse_button_event) = region_event { + handler(mouse_button_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Up, found {:?}", + region_event); + } + })); + self + } + + pub fn on_click( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::click_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::Click(mouse_button_event) = region_event { + handler(mouse_button_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Click, found {:?}", + region_event); + } + })); + self + } + + pub fn on_down_out( + mut self, + button: MouseButton, + handler: impl Fn(MouseButtonEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::down_out_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::DownOut(mouse_button_event) = region_event { + handler(mouse_button_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DownOut, found {:?}", + region_event); + } + })); + self + } + + pub fn on_drag( + mut self, + button: MouseButton, + handler: impl Fn(Vector2F, MouseMovedEvent, &mut EventContext) + 'static, + ) -> Self { + self.set.insert((MouseRegionEvent::drag_disc(), Some(button)), + Rc::new(move |region_event, cx| { + if let MouseRegionEvent::Drag(prev_drag_position, mouse_moved_event) = region_event { + handler(prev_drag_position, mouse_moved_event, cx); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Drag, 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); + } else { + panic!( + "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::Hover, found {:?}", + region_event); + } + })); + self + } +} + +#[derive(Debug)] +pub enum MouseRegionEvent { + Move(MouseMovedEvent), + Drag(Vector2F, MouseMovedEvent), + Hover(bool, MouseMovedEvent), + Down(MouseButtonEvent), + Up(MouseButtonEvent), + Click(MouseButtonEvent), + DownOut(MouseButtonEvent), + ScrollWheel(ScrollWheelEvent), +} + +impl MouseRegionEvent { + pub fn move_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Move(Default::default())) + } + pub fn drag_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Drag( + Default::default(), + Default::default(), + )) + } + pub fn hover_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Hover( + Default::default(), + Default::default(), + )) + } + pub fn down_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Down(Default::default())) + } + pub fn up_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Up(Default::default())) + } + pub fn click_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::Click(Default::default())) + } + pub fn down_out_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::DownOut(Default::default())) + } + pub fn scroll_wheel_disc() -> Discriminant { + std::mem::discriminant(&MouseRegionEvent::ScrollWheel(Default::default())) + } + + pub fn handler_key(&self) -> (Discriminant, Option) { + match self { + MouseRegionEvent::Move(_) => (Self::move_disc(), None), + MouseRegionEvent::Drag(_, MouseMovedEvent { pressed_button, .. }) => { + (Self::drag_disc(), *pressed_button) + } + MouseRegionEvent::Hover(_, _) => (Self::hover_disc(), None), + MouseRegionEvent::Down(MouseButtonEvent { button, .. }) => { + (Self::down_disc(), Some(*button)) + } + MouseRegionEvent::Up(MouseButtonEvent { button, .. }) => { + (Self::up_disc(), Some(*button)) + } + MouseRegionEvent::Click(MouseButtonEvent { button, .. }) => { + (Self::click_disc(), Some(*button)) + } + MouseRegionEvent::DownOut(MouseButtonEvent { button, .. }) => { + (Self::down_out_disc(), Some(*button)) + } + MouseRegionEvent::ScrollWheel(_) => (Self::scroll_wheel_disc(), None), + } + } +}