From f55a97b738096d85086858026234ee95dcd79289 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 13 Apr 2023 06:46:33 +0200 Subject: Rename `MouseListener` to `MouseArea` --- native/src/widget.rs | 4 +- native/src/widget/helpers.rs | 6 +- native/src/widget/mouse_area.rs | 353 ++++++++++++++++++++++++++++++++++++ native/src/widget/mouse_listener.rs | 353 ------------------------------------ 4 files changed, 358 insertions(+), 358 deletions(-) create mode 100644 native/src/widget/mouse_area.rs delete mode 100644 native/src/widget/mouse_listener.rs (limited to 'native') diff --git a/native/src/widget.rs b/native/src/widget.rs index 4eb3d1ba..6849da17 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -17,7 +17,7 @@ pub mod column; pub mod container; pub mod helpers; pub mod image; -pub mod mouse_listener; +pub mod mouse_area; pub mod operation; pub mod pane_grid; pub mod pick_list; @@ -52,7 +52,7 @@ pub use helpers::*; #[doc(no_inline)] pub use image::Image; #[doc(no_inline)] -pub use mouse_listener::MouseListener; +pub use mouse_area::MouseArea; #[doc(no_inline)] pub use pane_grid::PaneGrid; #[doc(no_inline)] diff --git a/native/src/widget/helpers.rs b/native/src/widget/helpers.rs index 88986d60..5f44e22c 100644 --- a/native/src/widget/helpers.rs +++ b/native/src/widget/helpers.rs @@ -316,11 +316,11 @@ where } /// A container intercepting mouse events. -pub fn mouse_listener<'a, Message, Renderer>( +pub fn mouse_area<'a, Message, Renderer>( widget: impl Into>, -) -> widget::MouseListener<'a, Message, Renderer> +) -> widget::MouseArea<'a, Message, Renderer> where Renderer: crate::Renderer, { - widget::MouseListener::new(widget) + widget::MouseArea::new(widget) } diff --git a/native/src/widget/mouse_area.rs b/native/src/widget/mouse_area.rs new file mode 100644 index 00000000..1b8b318c --- /dev/null +++ b/native/src/widget/mouse_area.rs @@ -0,0 +1,353 @@ +//! A container for capturing mouse events. + +use crate::event::{self, Event}; +use crate::layout; +use crate::mouse; +use crate::overlay; +use crate::renderer; +use crate::touch; +use crate::widget::{tree, Operation, Tree}; +use crate::{ + Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget, +}; + +/// Emit messages on mouse events. +#[allow(missing_debug_implementations)] +pub struct MouseArea<'a, Message, Renderer> { + content: Element<'a, Message, Renderer>, + on_press: Option, + on_release: Option, + on_right_press: Option, + on_right_release: Option, + on_middle_press: Option, + on_middle_release: Option, + on_mouse_enter: Option, + on_mouse_exit: Option, +} + +impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { + /// The message to emit on a left button press. + #[must_use] + pub fn on_press(mut self, message: Message) -> Self { + self.on_press = Some(message); + self + } + + /// The message to emit on a left button release. + #[must_use] + pub fn on_release(mut self, message: Message) -> Self { + self.on_release = Some(message); + self + } + + /// The message to emit on a right button press. + #[must_use] + pub fn on_right_press(mut self, message: Message) -> Self { + self.on_right_press = Some(message); + self + } + + /// The message to emit on a right button release. + #[must_use] + pub fn on_right_release(mut self, message: Message) -> Self { + self.on_right_release = Some(message); + self + } + + /// The message to emit on a middle button press. + #[must_use] + pub fn on_middle_press(mut self, message: Message) -> Self { + self.on_middle_press = Some(message); + self + } + + /// The message to emit on a middle button release. + #[must_use] + pub fn on_middle_release(mut self, message: Message) -> Self { + self.on_middle_release = Some(message); + self + } + + /// The message to emit when the mouse enters the widget. + #[must_use] + pub fn on_mouse_enter(mut self, message: Message) -> Self { + self.on_mouse_enter = Some(message); + self + } + + /// The messsage to emit when the mouse exits the widget. + #[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 { + is_hovered: bool, +} + +impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> { + /// Creates an empty [`MouseArea`]. + pub fn new(content: impl Into>) -> Self { + MouseArea { + content: content.into(), + on_press: None, + on_release: None, + on_right_press: None, + on_right_release: None, + on_middle_press: None, + on_middle_release: None, + on_mouse_enter: None, + on_mouse_exit: None, + } + } +} + +impl<'a, Message, Renderer> Widget + for MouseArea<'a, Message, Renderer> +where + Renderer: crate::Renderer, + Message: Clone, +{ + fn tag(&self) -> tree::Tag { + tree::Tag::of::() + } + + fn state(&self) -> tree::State { + tree::State::new(State::default()) + } + + fn children(&self) -> Vec { + vec![Tree::new(&self.content)] + } + + fn diff(&self, tree: &mut Tree) { + tree.diff_children(std::slice::from_ref(&self.content)); + } + + fn width(&self) -> Length { + self.content.as_widget().width() + } + + fn height(&self) -> Length { + self.content.as_widget().height() + } + + fn layout( + &self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + self.content.as_widget().layout(renderer, limits) + } + + fn operate( + &self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn Operation, + ) { + self.content.as_widget().operate( + &mut tree.children[0], + layout, + renderer, + operation, + ); + } + + fn on_event( + &mut self, + tree: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor_position: Point, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, Message>, + ) -> event::Status { + if let event::Status::Captured = self.content.as_widget_mut().on_event( + &mut tree.children[0], + event.clone(), + layout, + cursor_position, + renderer, + clipboard, + shell, + ) { + return event::Status::Captured; + } + + update( + self, + &event, + layout, + cursor_position, + shell, + tree.state.downcast_mut::(), + ) + } + + fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.content.as_widget().mouse_interaction( + &tree.children[0], + layout, + cursor_position, + viewport, + renderer, + ) + } + + fn draw( + &self, + tree: &Tree, + renderer: &mut Renderer, + theme: &Renderer::Theme, + renderer_style: &renderer::Style, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + ) { + self.content.as_widget().draw( + &tree.children[0], + renderer, + theme, + renderer_style, + layout, + cursor_position, + viewport, + ); + } + + fn overlay<'b>( + &'b mut self, + tree: &'b mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + ) -> Option> { + self.content.as_widget_mut().overlay( + &mut tree.children[0], + layout, + renderer, + ) + } +} + +impl<'a, Message, Renderer> From> + for Element<'a, Message, Renderer> +where + Message: 'a + Clone, + Renderer: 'a + crate::Renderer, +{ + fn from( + area: MouseArea<'a, Message, Renderer>, + ) -> Element<'a, Message, Renderer> { + Element::new(area) + } +} + +/// Processes the given [`Event`] and updates the [`State`] of an [`MouseArea`] +/// accordingly. +fn update( + widget: &mut MouseArea<'_, Message, Renderer>, + event: &Event, + layout: Layout<'_>, + cursor_position: Point, + shell: &mut Shell<'_, Message>, + state: &mut State, +) -> event::Status { + let was_hovered = state.is_hovered; + + state.is_hovered = layout.bounds().contains(cursor_position); + + if !state.is_hovered { + if was_hovered { + if let Some(message) = widget.on_mouse_exit.as_ref() { + shell.publish(message.clone()); + } + } + + return event::Status::Ignored; + } + + if !was_hovered { + if let Some(message) = widget.on_mouse_enter.as_ref() { + shell.publish(message.clone()); + } + } + + if let Some(message) = widget.on_press.as_ref() { + if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) = event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + if let Some(message) = widget.on_release.as_ref() { + if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerLifted { .. }) = event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + if let Some(message) = widget.on_right_press.as_ref() { + if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) = + event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + if let Some(message) = widget.on_right_release.as_ref() { + if let Event::Mouse(mouse::Event::ButtonReleased( + mouse::Button::Right, + )) = event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + if let Some(message) = widget.on_middle_press.as_ref() { + if let Event::Mouse(mouse::Event::ButtonPressed( + mouse::Button::Middle, + )) = event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + if let Some(message) = widget.on_middle_release.as_ref() { + if let Event::Mouse(mouse::Event::ButtonReleased( + mouse::Button::Middle, + )) = event + { + shell.publish(message.clone()); + + return event::Status::Captured; + } + } + + event::Status::Ignored +} diff --git a/native/src/widget/mouse_listener.rs b/native/src/widget/mouse_listener.rs deleted file mode 100644 index 00e20c04..00000000 --- a/native/src/widget/mouse_listener.rs +++ /dev/null @@ -1,353 +0,0 @@ -//! A container for capturing mouse events. - -use crate::event::{self, Event}; -use crate::layout; -use crate::mouse; -use crate::overlay; -use crate::renderer; -use crate::touch; -use crate::widget::{tree, Operation, Tree}; -use crate::{ - Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget, -}; - -/// Emit messages on mouse events. -#[allow(missing_debug_implementations)] -pub struct MouseListener<'a, Message, Renderer> { - content: Element<'a, Message, Renderer>, - on_press: Option, - on_release: Option, - on_right_press: Option, - on_right_release: Option, - on_middle_press: Option, - on_middle_release: Option, - on_mouse_enter: Option, - on_mouse_exit: Option, -} - -impl<'a, Message, Renderer> MouseListener<'a, Message, Renderer> { - /// The message to emit on a left button press. - #[must_use] - pub fn on_press(mut self, message: Message) -> Self { - self.on_press = Some(message); - self - } - - /// The message to emit on a left button release. - #[must_use] - pub fn on_release(mut self, message: Message) -> Self { - self.on_release = Some(message); - self - } - - /// The message to emit on a right button press. - #[must_use] - pub fn on_right_press(mut self, message: Message) -> Self { - self.on_right_press = Some(message); - self - } - - /// The message to emit on a right button release. - #[must_use] - pub fn on_right_release(mut self, message: Message) -> Self { - self.on_right_release = Some(message); - self - } - - /// The message to emit on a middle button press. - #[must_use] - pub fn on_middle_press(mut self, message: Message) -> Self { - self.on_middle_press = Some(message); - self - } - - /// The message to emit on a middle button release. - #[must_use] - pub fn on_middle_release(mut self, message: Message) -> Self { - self.on_middle_release = Some(message); - self - } - - /// The message to emit when the mouse enters the widget. - #[must_use] - pub fn on_mouse_enter(mut self, message: Message) -> Self { - self.on_mouse_enter = Some(message); - self - } - - /// The messsage to emit when the mouse exits the widget. - #[must_use] - pub fn on_mouse_exit(mut self, message: Message) -> Self { - self.on_mouse_exit = Some(message); - self - } -} - -/// Local state of the [`MouseListener`]. -#[derive(Default)] -struct State { - is_hovered: bool, -} - -impl<'a, Message, Renderer> MouseListener<'a, Message, Renderer> { - /// Creates an empty [`MouseListener`]. - pub fn new(content: impl Into>) -> Self { - MouseListener { - content: content.into(), - on_press: None, - on_release: None, - on_right_press: None, - on_right_release: None, - on_middle_press: None, - on_middle_release: None, - on_mouse_enter: None, - on_mouse_exit: None, - } - } -} - -impl<'a, Message, Renderer> Widget - for MouseListener<'a, Message, Renderer> -where - Renderer: crate::Renderer, - Message: Clone, -{ - fn tag(&self) -> tree::Tag { - tree::Tag::of::() - } - - fn state(&self) -> tree::State { - tree::State::new(State::default()) - } - - fn children(&self) -> Vec { - vec![Tree::new(&self.content)] - } - - fn diff(&self, tree: &mut Tree) { - tree.diff_children(std::slice::from_ref(&self.content)); - } - - fn width(&self) -> Length { - self.content.as_widget().width() - } - - fn height(&self) -> Length { - self.content.as_widget().height() - } - - fn layout( - &self, - renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - self.content.as_widget().layout(renderer, limits) - } - - fn operate( - &self, - tree: &mut Tree, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn Operation, - ) { - self.content.as_widget().operate( - &mut tree.children[0], - layout, - renderer, - operation, - ); - } - - fn on_event( - &mut self, - tree: &mut Tree, - event: Event, - layout: Layout<'_>, - cursor_position: Point, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - ) -> event::Status { - if let event::Status::Captured = self.content.as_widget_mut().on_event( - &mut tree.children[0], - event.clone(), - layout, - cursor_position, - renderer, - clipboard, - shell, - ) { - return event::Status::Captured; - } - - update( - self, - &event, - layout, - cursor_position, - shell, - tree.state.downcast_mut::(), - ) - } - - fn mouse_interaction( - &self, - tree: &Tree, - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.content.as_widget().mouse_interaction( - &tree.children[0], - layout, - cursor_position, - viewport, - renderer, - ) - } - - fn draw( - &self, - tree: &Tree, - renderer: &mut Renderer, - theme: &Renderer::Theme, - renderer_style: &renderer::Style, - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - ) { - self.content.as_widget().draw( - &tree.children[0], - renderer, - theme, - renderer_style, - layout, - cursor_position, - viewport, - ); - } - - fn overlay<'b>( - &'b mut self, - tree: &'b mut Tree, - layout: Layout<'_>, - renderer: &Renderer, - ) -> Option> { - self.content.as_widget_mut().overlay( - &mut tree.children[0], - layout, - renderer, - ) - } -} - -impl<'a, Message, Renderer> From> - for Element<'a, Message, Renderer> -where - Message: 'a + Clone, - Renderer: 'a + crate::Renderer, -{ - fn from( - listener: MouseListener<'a, Message, Renderer>, - ) -> Element<'a, Message, Renderer> { - Element::new(listener) - } -} - -/// Processes the given [`Event`] and updates the [`State`] of an [`MouseListener`] -/// accordingly. -fn update( - widget: &mut MouseListener<'_, Message, Renderer>, - event: &Event, - layout: Layout<'_>, - cursor_position: Point, - shell: &mut Shell<'_, Message>, - state: &mut State, -) -> event::Status { - let was_hovered = state.is_hovered; - - state.is_hovered = layout.bounds().contains(cursor_position); - - if !state.is_hovered { - if was_hovered { - if let Some(message) = widget.on_mouse_exit.as_ref() { - shell.publish(message.clone()); - } - } - - return event::Status::Ignored; - } - - if !was_hovered { - if let Some(message) = widget.on_mouse_enter.as_ref() { - shell.publish(message.clone()); - } - } - - if let Some(message) = widget.on_press.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) = event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - if let Some(message) = widget.on_release.as_ref() { - if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerLifted { .. }) = event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - if let Some(message) = widget.on_right_press.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) = - event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - if let Some(message) = widget.on_right_release.as_ref() { - if let Event::Mouse(mouse::Event::ButtonReleased( - mouse::Button::Right, - )) = event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - if let Some(message) = widget.on_middle_press.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Middle, - )) = event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - if let Some(message) = widget.on_middle_release.as_ref() { - if let Event::Mouse(mouse::Event::ButtonReleased( - mouse::Button::Middle, - )) = event - { - shell.publish(message.clone()); - - return event::Status::Captured; - } - } - - event::Status::Ignored -} -- cgit