summaryrefslogtreecommitdiffstats
path: root/widget
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector@hecrj.dev>2024-02-03 18:17:42 +0100
committerLibravatar GitHub <noreply@github.com>2024-02-03 18:17:42 +0100
commit6756594fc6edc699f8a254c369aabdecc4e2dcea (patch)
treef1a9141d8a15168c9ff33eb2a6fcd62a82861e7c /widget
parent1d58d44fad605e428e7c203f610d3f98e53970d7 (diff)
parent3da6afdc413c19e6ec75f02a037089df95da8126 (diff)
downloadiced-6756594fc6edc699f8a254c369aabdecc4e2dcea.tar.gz
iced-6756594fc6edc699f8a254c369aabdecc4e2dcea.tar.bz2
iced-6756594fc6edc699f8a254c369aabdecc4e2dcea.zip
Merge pull request #2147 from Remmirad/mouse_area_hover_events
Add mouse move events to MouseArea
Diffstat (limited to '')
-rw-r--r--widget/src/mouse_area.rs69
1 files changed, 66 insertions, 3 deletions
diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs
index 88f7d126..f82a75f4 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 Fn(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: Fn(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
+ is_hovered: 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,42 @@ where
/// accordingly.
fn update<Message: Clone, Theme, Renderer>(
widget: &mut MouseArea<'_, Message, Theme, Renderer>,
- event: &Event,
+ tree: &mut Tree,
+ event: Event,
layout: Layout<'_>,
cursor: mouse::Cursor,
shell: &mut Shell<'_, Message>,
) -> event::Status {
+ if let Event::Mouse(mouse::Event::CursorMoved { .. })
+ | Event::Touch(touch::Event::FingerMoved { .. }) = event
+ {
+ let state: &mut State = tree.state.downcast_mut();
+
+ 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()) {
return event::Status::Ignored;
}