Add mouse move events to MouseArea
This commit is contained in:
parent
1d58d44fad
commit
ce23498edf
1 changed files with 73 additions and 2 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
//! A container for capturing mouse events.
|
//! A container for capturing mouse events.
|
||||||
|
|
||||||
|
use iced_renderer::core::Point;
|
||||||
|
|
||||||
use crate::core::event::{self, Event};
|
use crate::core::event::{self, Event};
|
||||||
use crate::core::layout;
|
use crate::core::layout;
|
||||||
use crate::core::mouse;
|
use crate::core::mouse;
|
||||||
|
|
@ -26,6 +28,9 @@ pub struct MouseArea<
|
||||||
on_right_release: Option<Message>,
|
on_right_release: Option<Message>,
|
||||||
on_middle_press: Option<Message>,
|
on_middle_press: Option<Message>,
|
||||||
on_middle_release: 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> {
|
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.on_middle_release = Some(message);
|
||||||
self
|
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`].
|
/// Local state of the [`MouseArea`].
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct State {
|
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> {
|
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_right_release: None,
|
||||||
on_middle_press: None,
|
on_middle_press: None,
|
||||||
on_middle_release: 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;
|
return event::Status::Captured;
|
||||||
}
|
}
|
||||||
|
|
||||||
update(self, &event, layout, cursor, shell)
|
update(self, tree, &event, layout, cursor, shell)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_interaction(
|
fn mouse_interaction(
|
||||||
|
|
@ -246,11 +278,19 @@ where
|
||||||
/// accordingly.
|
/// accordingly.
|
||||||
fn update<Message: Clone, Theme, Renderer>(
|
fn update<Message: Clone, Theme, Renderer>(
|
||||||
widget: &mut MouseArea<'_, Message, Theme, Renderer>,
|
widget: &mut MouseArea<'_, Message, Theme, Renderer>,
|
||||||
|
tree: &mut Tree,
|
||||||
event: &Event,
|
event: &Event,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor: mouse::Cursor,
|
cursor: mouse::Cursor,
|
||||||
shell: &mut Shell<'_, Message>,
|
shell: &mut Shell<'_, Message>,
|
||||||
) -> event::Status {
|
) -> 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()) {
|
if !cursor.is_over(layout.bounds()) {
|
||||||
return event::Status::Ignored;
|
return event::Status::Ignored;
|
||||||
}
|
}
|
||||||
|
|
@ -320,3 +360,34 @@ fn update<Message: Clone, Theme, Renderer>(
|
||||||
|
|
||||||
event::Status::Ignored
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue