Extract handler set from MouseRegion

This commit is contained in:
K Simmons 2022-07-18 09:54:48 -07:00
parent 8add81350e
commit ec25fa9260
3 changed files with 332 additions and 253 deletions

View file

@ -252,7 +252,6 @@ impl Presenter {
} else if let Some(handler) = region } else if let Some(handler) = region
.handlers .handlers
.get(&(MouseRegionEvent::down_out_disc(), Some(*button))) .get(&(MouseRegionEvent::down_out_disc(), Some(*button)))
.cloned()
{ {
mouse_down_out_handlers.push(( mouse_down_out_handlers.push((
handler, handler,

View file

@ -1,7 +1,8 @@
use collections::HashMap; mod mouse_region;
use serde::Deserialize; use serde::Deserialize;
use serde_json::json; use serde_json::json;
use std::{any::TypeId, borrow::Cow, mem::Discriminant, rc::Rc, sync::Arc}; use std::{borrow::Cow, sync::Arc};
use crate::{ use crate::{
color::Color, color::Color,
@ -9,8 +10,9 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F}, geometry::{rect::RectF, vector::Vector2F},
json::ToJson, json::ToJson,
platform::CursorStyle, platform::CursorStyle,
EventContext, ImageData, MouseButton, MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent, ImageData,
}; };
pub use mouse_region::*;
pub struct Scene { pub struct Scene {
scale_factor: f32, scale_factor: f32,
@ -45,255 +47,6 @@ pub struct CursorRegion {
pub style: CursorStyle, 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<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Move(Default::default()))
}
pub fn drag_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Drag(
Default::default(),
Default::default(),
))
}
pub fn hover_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Hover(
Default::default(),
Default::default(),
))
}
pub fn down_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Down(Default::default()))
}
pub fn up_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Up(Default::default()))
}
pub fn click_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Click(Default::default()))
}
pub fn down_out_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::DownOut(Default::default()))
}
pub fn scroll_wheel_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::ScrollWheel(Default::default()))
}
pub fn handler_key(&self) -> (Discriminant<MouseRegionEvent>, Option<MouseButton>) {
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<MouseRegionEvent>, Option<MouseButton>),
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
>,
}
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<MouseRegionEvent>, Option<MouseButton>),
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
> = 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)] #[derive(Default, Debug)]
pub struct Quad { pub struct Quad {
pub bounds: RectF, pub bounds: RectF,

View file

@ -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<MouseRegionEvent>, Option<MouseButton>),
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
>,
}
impl HandlerSet {
pub fn handle_all() -> Self {
let mut set: HashMap<
(Discriminant<MouseRegionEvent>, Option<MouseButton>),
Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>,
> = 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<MouseRegionEvent>, Option<MouseButton>),
) -> Option<Rc<dyn Fn(MouseRegionEvent, &mut EventContext)>> {
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<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Move(Default::default()))
}
pub fn drag_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Drag(
Default::default(),
Default::default(),
))
}
pub fn hover_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Hover(
Default::default(),
Default::default(),
))
}
pub fn down_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Down(Default::default()))
}
pub fn up_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Up(Default::default()))
}
pub fn click_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::Click(Default::default()))
}
pub fn down_out_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::DownOut(Default::default()))
}
pub fn scroll_wheel_disc() -> Discriminant<MouseRegionEvent> {
std::mem::discriminant(&MouseRegionEvent::ScrollWheel(Default::default()))
}
pub fn handler_key(&self) -> (Discriminant<MouseRegionEvent>, Option<MouseButton>) {
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),
}
}
}