Introduce MouseEventHandler::on_drag

This commit is contained in:
Antonio Scandurra 2021-08-27 14:30:08 +02:00
parent 386631debf
commit 8a10234b14

View file

@ -9,12 +9,14 @@ pub struct MouseEventHandler {
state: ValueHandle<MouseState>, state: ValueHandle<MouseState>,
child: ElementBox, child: ElementBox,
click_handler: Option<Box<dyn FnMut(&mut EventContext)>>, click_handler: Option<Box<dyn FnMut(&mut EventContext)>>,
drag_handler: Option<Box<dyn FnMut(Vector2F, &mut EventContext)>>,
} }
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct MouseState { pub struct MouseState {
pub hovered: bool, pub hovered: bool,
pub clicked: bool, pub clicked: bool,
prev_drag_position: Option<Vector2F>,
} }
impl MouseEventHandler { impl MouseEventHandler {
@ -30,6 +32,7 @@ impl MouseEventHandler {
state: state_handle, state: state_handle,
child, child,
click_handler: None, click_handler: None,
drag_handler: None,
} }
} }
@ -37,6 +40,11 @@ impl MouseEventHandler {
self.click_handler = Some(Box::new(handler)); self.click_handler = Some(Box::new(handler));
self self
} }
pub fn on_drag(mut self, handler: impl FnMut(Vector2F, &mut EventContext) + 'static) -> Self {
self.drag_handler = Some(Box::new(handler));
self
}
} }
impl Element for MouseEventHandler { impl Element for MouseEventHandler {
@ -69,6 +77,7 @@ impl Element for MouseEventHandler {
cx: &mut EventContext, cx: &mut EventContext,
) -> bool { ) -> bool {
let click_handler = self.click_handler.as_mut(); let click_handler = self.click_handler.as_mut();
let drag_handler = self.drag_handler.as_mut();
let handled_in_child = self.child.dispatch_event(event, cx); let handled_in_child = self.child.dispatch_event(event, cx);
@ -86,6 +95,7 @@ impl Element for MouseEventHandler {
Event::LeftMouseDown { position, .. } => { Event::LeftMouseDown { position, .. } => {
if !handled_in_child && bounds.contains_point(*position) { if !handled_in_child && bounds.contains_point(*position) {
state.clicked = true; state.clicked = true;
state.prev_drag_position = Some(*position);
cx.notify(); cx.notify();
true true
} else { } else {
@ -93,6 +103,7 @@ impl Element for MouseEventHandler {
} }
} }
Event::LeftMouseUp { position, .. } => { Event::LeftMouseUp { position, .. } => {
state.prev_drag_position = None;
if !handled_in_child && state.clicked { if !handled_in_child && state.clicked {
state.clicked = false; state.clicked = false;
cx.notify(); cx.notify();
@ -106,6 +117,20 @@ impl Element for MouseEventHandler {
handled_in_child handled_in_child
} }
} }
Event::LeftMouseDragged { position, .. } => {
if !handled_in_child && state.clicked {
let prev_drag_position = state.prev_drag_position.replace(*position);
if let Some((handler, prev_position)) = drag_handler.zip(prev_drag_position) {
let delta = *position - prev_position;
if !delta.is_zero() {
(handler)(delta, cx);
}
}
true
} else {
handled_in_child
}
}
_ => handled_in_child, _ => handled_in_child,
}) })
} }