diff options
author | 2023-11-26 14:25:19 +0100 | |
---|---|---|
committer | 2024-02-03 17:52:39 +0100 | |
commit | ce23498edf1e84ab7f70394ec21da1c8c466a444 (patch) | |
tree | 2b7ebb5c9a566469b4fc85e06a719d5866ec7a36 /widget | |
parent | 1d58d44fad605e428e7c203f610d3f98e53970d7 (diff) | |
download | iced-ce23498edf1e84ab7f70394ec21da1c8c466a444.tar.gz iced-ce23498edf1e84ab7f70394ec21da1c8c466a444.tar.bz2 iced-ce23498edf1e84ab7f70394ec21da1c8c466a444.zip |
Add mouse move events to `MouseArea`
Diffstat (limited to 'widget')
-rw-r--r-- | widget/src/mouse_area.rs | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index 88f7d126..1487aaa5 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -1,5 +1,7 @@ //! A container for capturing mouse events. +use iced_renderer::core::Point; + use crate::core::event::{self, Event}; use crate::core::layout; use crate::core::mouse; @@ -26,6 +28,9 @@ pub struct MouseArea< on_right_release: Option<Message>, on_middle_press: Option<Message>, on_middle_release: Option<Message>, + on_mouse_enter: Option<Message>, + on_mouse_move: Option<Box<dyn FnMut(Point) -> Message>>, + on_mouse_exit: Option<Message>, } impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { @@ -70,12 +75,36 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { self.on_middle_release = Some(message); self } + + /// The message to emit when the mouse enters the area. + #[must_use] + pub fn on_mouse_enter(mut self, message: Message) -> Self { + self.on_mouse_enter = Some(message); + self + } + + /// The message to emit when the mouse moves in the area. + #[must_use] + pub fn on_mouse_move<F>(mut self, build_message: F) -> Self + where + F: FnMut(Point) -> Message + 'static, + { + self.on_mouse_move = Some(Box::new(build_message)); + self + } + + /// The message to emit when the mouse exits the area. + #[must_use] + pub fn on_mouse_exit(mut self, message: Message) -> Self { + self.on_mouse_exit = Some(message); + self + } } /// Local state of the [`MouseArea`]. #[derive(Default)] struct State { - // TODO: Support on_mouse_enter and on_mouse_exit + mouse_in_area: bool, } impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { @@ -91,6 +120,9 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { on_right_release: None, on_middle_press: None, on_middle_release: None, + on_mouse_enter: None, + on_mouse_move: None, + on_mouse_exit: None, } } } @@ -171,7 +203,7 @@ where return event::Status::Captured; } - update(self, &event, layout, cursor, shell) + update(self, tree, &event, layout, cursor, shell) } fn mouse_interaction( @@ -246,11 +278,19 @@ where /// accordingly. fn update<Message: Clone, Theme, Renderer>( widget: &mut MouseArea<'_, Message, Theme, Renderer>, + tree: &mut Tree, 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 + { + let state: &mut State = tree.state.downcast_mut(); + handle_mouse_move(widget, state, shell, *position, layout.bounds()) + } + if !cursor.is_over(layout.bounds()) { return event::Status::Ignored; } @@ -320,3 +360,34 @@ fn update<Message: Clone, Theme, Renderer>( event::Status::Ignored } + +fn handle_mouse_move<Message: Clone, Theme, Renderer>( + 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; +} |