summaryrefslogtreecommitdiffstats
path: root/widget/src
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src')
-rw-r--r--widget/src/mouse_area.rs75
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;
+}