Skip to content

Commit

Permalink
feat(mouse-area): added on_drag method
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick committed Sep 12, 2023
1 parent 497edfc commit c7b345e
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion widget/src/mouse_area.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Message>,
on_press: Option<Message>,
on_release: Option<Message>,
on_right_press: Option<Message>,
Expand All @@ -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 {
Expand Down Expand Up @@ -73,13 +82,15 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> {
#[derive(Default)]
struct State {
// TODO: Support on_mouse_enter and on_mouse_exit
drag_initiated: Option<Point>,
}

impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> {
/// Creates a [`MouseArea`] with the given content.
pub fn new(content: impl Into<Element<'a, Message, Renderer>>) -> Self {
MouseArea {
content: content.into(),
on_drag: None,
on_press: None,
on_release: None,
on_right_press: None,
Expand Down Expand Up @@ -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::<State>(),
)
}

fn mouse_interaction(
Expand Down Expand Up @@ -243,6 +261,7 @@ fn update<Message: Clone, Renderer>(
layout: Layout<'_>,
cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>,
state: &mut State,
) -> event::Status {
if !cursor.is_over(layout.bounds()) {
return event::Status::Ignored;
Expand All @@ -252,6 +271,7 @@ fn update<Message: Clone, Renderer>(
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;
Expand All @@ -262,6 +282,7 @@ fn update<Message: Clone, Renderer>(
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;
Expand Down Expand Up @@ -311,5 +332,24 @@ fn update<Message: Clone, Renderer>(
}
}

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
}

0 comments on commit c7b345e

Please sign in to comment.