From c7b345ec511c5fb2591f07a33ec5822ccc59db60 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 12 Sep 2023 17:53:44 +0200 Subject: [PATCH] feat(mouse-area): added on_drag method --- widget/src/mouse_area.rs | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index 18efcebd03..785e545db3 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -1,6 +1,7 @@ //! A container for capturing mouse events. use iced_renderer::core::widget::OperationOutputWrapper; +use iced_renderer::core::Point; use crate::core::event::{self, Event}; use crate::core::layout; @@ -17,6 +18,7 @@ use crate::core::{ #[allow(missing_debug_implementations)] pub struct MouseArea<'a, Message, Renderer> { content: Element<'a, Message, Renderer>, + on_drag: Option, on_press: Option, on_release: Option, on_right_press: Option, @@ -26,6 +28,13 @@ pub struct MouseArea<'a, Message, Renderer> { } impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { + /// The message to emit when a drag is initiated. + #[must_use] + pub fn on_drag(mut self, message: Message) -> Self { + self.on_drag = Some(message); + self + } + /// The message to emit on a left button press. #[must_use] pub fn on_press(mut self, message: Message) -> Self { @@ -73,6 +82,7 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { #[derive(Default)] struct State { // TODO: Support on_mouse_enter and on_mouse_exit + drag_initiated: Option, } impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { @@ -80,6 +90,7 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { pub fn new(content: impl Into>) -> Self { MouseArea { content: content.into(), + on_drag: None, on_press: None, on_release: None, on_right_press: None, @@ -167,7 +178,14 @@ where return event::Status::Captured; } - update(self, &event, layout, cursor, shell) + update( + self, + &event, + layout, + cursor, + shell, + tree.state.downcast_mut::(), + ) } fn mouse_interaction( @@ -243,6 +261,7 @@ fn update( layout: Layout<'_>, cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, + state: &mut State, ) -> event::Status { if !cursor.is_over(layout.bounds()) { return event::Status::Ignored; @@ -252,6 +271,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) = event { + state.drag_initiated = cursor.position(); shell.publish(message.clone()); return event::Status::Captured; @@ -262,6 +282,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. }) = event { + state.drag_initiated = None; shell.publish(message.clone()); return event::Status::Captured; @@ -311,5 +332,24 @@ fn update( } } + if state.drag_initiated.is_none() && widget.on_drag.is_some() { + if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) = event + { + state.drag_initiated = cursor.position(); + } + } else if let Some((message, drag_source)) = + widget.on_drag.as_ref().zip(state.drag_initiated) + { + if let Some(position) = cursor.position() { + if position.distance(drag_source) > 1.0 { + state.drag_initiated = None; + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + } + event::Status::Ignored }