From 8ea85f3b12c087560fdfeeebd8eb3c6efd754bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 3 Feb 2024 18:05:40 +0100 Subject: [PATCH] Use `Fn` instead of `FnMut` in `MouseArea` ... and simplify event logic a bit. --- widget/src/mouse_area.rs | 70 ++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index a216643694..f82a75f406 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -29,7 +29,7 @@ pub struct MouseArea< on_middle_press: Option, on_middle_release: Option, on_mouse_enter: Option, - on_mouse_move: Option Message>>, + on_mouse_move: Option Message>>, on_mouse_exit: Option, } @@ -87,7 +87,7 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { #[must_use] pub fn on_mouse_move(mut self, build_message: F) -> Self where - F: FnMut(Point) -> Message + 'static, + F: Fn(Point) -> Message + 'static, { self.on_mouse_move = Some(Box::new(build_message)); self @@ -104,7 +104,7 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// Local state of the [`MouseArea`]. #[derive(Default)] struct State { - mouse_in_area: bool, + is_hovered: bool, } impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { @@ -203,7 +203,7 @@ where return event::Status::Captured; } - update(self, tree, &event, layout, cursor, shell) + update(self, tree, event, layout, cursor, shell) } fn mouse_interaction( @@ -279,16 +279,39 @@ where fn update( widget: &mut MouseArea<'_, Message, Theme, Renderer>, tree: &mut Tree, - event: &Event, + event: Event, layout: Layout<'_>, cursor: mouse::Cursor, shell: &mut Shell<'_, Message>, ) -> event::Status { - if let Event::Mouse(mouse::Event::CursorMoved { position }) - | Event::Touch(touch::Event::FingerMoved { id: _, position }) = event + if let Event::Mouse(mouse::Event::CursorMoved { .. }) + | Event::Touch(touch::Event::FingerMoved { .. }) = event { let state: &mut State = tree.state.downcast_mut(); - handle_mouse_move(widget, state, shell, *position, layout.bounds()); + + let was_hovered = state.is_hovered; + state.is_hovered = cursor.is_over(layout.bounds()); + + match ( + widget.on_mouse_enter.as_ref(), + widget.on_mouse_move.as_ref(), + widget.on_mouse_exit.as_ref(), + ) { + (Some(on_mouse_enter), _, _) + if state.is_hovered && !was_hovered => + { + shell.publish(on_mouse_enter.clone()); + } + (_, Some(on_mouse_move), _) if state.is_hovered => { + if let Some(position) = cursor.position_in(layout.bounds()) { + shell.publish(on_mouse_move(position)); + } + } + (_, _, Some(on_mouse_exit)) if !state.is_hovered && was_hovered => { + shell.publish(on_mouse_exit.clone()); + } + _ => {} + } } if !cursor.is_over(layout.bounds()) { @@ -360,34 +383,3 @@ fn update( event::Status::Ignored } - -fn handle_mouse_move( - widget: &mut MouseArea<'_, Message, Theme, Renderer>, - state: &mut State, - shell: &mut Shell<'_, Message>, - position: Point, - area_bounds: Rectangle, -) { - let mouse_in_area = area_bounds.contains(position); - - match ( - widget.on_mouse_enter.as_mut(), - widget.on_mouse_move.as_mut(), - widget.on_mouse_exit.as_mut(), - ) { - (Some(enter_msg), _, _) if mouse_in_area && !state.mouse_in_area => { - shell.publish(enter_msg.clone()); - } - (_, Some(build_move_msg), _) - if mouse_in_area && state.mouse_in_area => - { - shell.publish(build_move_msg(position)); - } - (_, _, Some(exit_msg)) if !mouse_in_area && state.mouse_in_area => { - shell.publish(exit_msg.clone()); - } - _ => {} - } - - state.mouse_in_area = mouse_in_area; -}