From a0d097f72e75389c6a8c80739fbddac3d8832fef Mon Sep 17 00:00:00 2001 From: Bin Date: Mon, 4 Nov 2024 22:45:38 +0800 Subject: [PATCH 1/2] Add '_with' suffix related methods to MouseArea to support closures --- widget/src/mouse_area.rs | 167 ++++++++++++++++++++++++++++++++------- 1 file changed, 140 insertions(+), 27 deletions(-) diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index c5a37ae3f1..cdd29df4db 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -20,32 +20,68 @@ pub struct MouseArea< Renderer = crate::Renderer, > { content: Element<'a, Message, Theme, Renderer>, - on_press: Option, - on_release: Option, - on_double_click: Option, - on_right_press: Option, - on_right_release: Option, - on_middle_press: Option, - on_middle_release: Option, + on_press: Option>, + on_release: Option>, + on_double_click: Option>, + on_right_press: Option>, + on_right_release: Option>, + on_middle_press: Option>, + on_middle_release: Option>, on_scroll: Option Message + 'a>>, - on_enter: Option, + on_enter: Option>, on_move: Option Message + 'a>>, - on_exit: Option, + on_exit: Option>, interaction: Option, } +enum OnPress<'a, Message> { + Direct(Message), + Closure(Box Message + 'a>), +} + +impl<'a, Message: Clone> OnPress<'a, Message> { + fn get(&self) -> Message { + match self { + OnPress::Direct(message) => message.clone(), + OnPress::Closure(f) => f(), + } + } +} + impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, 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.on_press = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_press`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_press_with( + mut self, + on_press: impl Fn() -> Message + 'a, + ) -> Self { + self.on_press = Some(OnPress::Closure(Box::new(on_press))); 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.on_release = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_release`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_release_with( + mut self, + on_release: impl Fn() -> Message + 'a, + ) -> Self { + self.on_release = Some(OnPress::Closure(Box::new(on_release))); self } @@ -61,35 +97,90 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// [`on_release`]: Self::on_release #[must_use] pub fn on_double_click(mut self, message: Message) -> Self { - self.on_double_click = Some(message); + self.on_double_click = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_double_click`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_double_click_with( + mut self, + on_double_click: impl Fn() -> Message + 'a + ) -> Self { + self.on_double_click = Some(OnPress::Closure(Box::new(on_double_click))); 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.on_right_press = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_right_press`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_right_press_with( + mut self, + on_right_press: impl Fn() -> Message + 'a, + ) -> Self { + self.on_right_press = Some(OnPress::Closure(Box::new(on_right_press))); 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.on_right_release = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_right_release`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_right_release_with( + mut self, + on_right_release: impl Fn() -> Message + 'a + ) -> Self { + self.on_right_release = Some(OnPress::Closure(Box::new(on_right_release))); 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.on_middle_press = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_middle_press`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_middle_press_with( + mut self, + on_middle_press: impl Fn() -> Message + 'a + ) -> Self { + self.on_middle_press = Some(OnPress::Closure(Box::new(on_middle_press))); 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.on_middle_release = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_middle_release`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_middle_release_with( + mut self, + on_middle_release: impl Fn() -> Message + 'a + ) -> Self { + self.on_middle_release = Some(OnPress::Closure(Box::new(on_middle_release))); self } @@ -106,7 +197,18 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// The message to emit when the mouse enters the area. #[must_use] pub fn on_enter(mut self, message: Message) -> Self { - self.on_enter = Some(message); + self.on_enter = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_enter`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_enter_with( + mut self, + on_enter: impl Fn() -> Message + 'a + ) -> Self { + self.on_enter = Some(OnPress::Closure(Box::new(on_enter))); self } @@ -120,7 +222,18 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// The message to emit when the mouse exits the area. #[must_use] pub fn on_exit(mut self, message: Message) -> Self { - self.on_exit = Some(message); + self.on_exit = Some(OnPress::Direct(message)); + self + } + + /// This is analogous to [`MouseArea::on_exit`], but using a closure to produce + /// the message. + #[must_use] + pub fn on_exit_with( + mut self, + on_exit: impl Fn() -> Message + 'a + ) -> Self { + self.on_exit = Some(OnPress::Closure(Box::new(on_exit))); self } @@ -348,7 +461,7 @@ fn update( widget.on_exit.as_ref(), ) { (Some(on_enter), _, _) if state.is_hovered && !was_hovered => { - shell.publish(on_enter.clone()); + shell.publish(on_enter.get().clone()); } (_, Some(on_move), _) if state.is_hovered => { if let Some(position) = cursor.position_in(layout.bounds()) { @@ -356,7 +469,7 @@ fn update( } } (_, _, Some(on_exit)) if !state.is_hovered && was_hovered => { - shell.publish(on_exit.clone()); + shell.publish(on_exit.get().clone()); } _ => {} } @@ -373,7 +486,7 @@ fn update( if let Some(message) = widget.on_press.as_ref() { captured = true; - shell.publish(message.clone()); + shell.publish(message.get().clone()); } if let Some(position) = cursor_position { @@ -385,7 +498,7 @@ fn update( ); if matches!(new_click.kind(), mouse::click::Kind::Double) { - shell.publish(message.clone()); + shell.publish(message.get().clone()); } state.previous_click = Some(new_click); @@ -405,7 +518,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. }) = event { - shell.publish(message.clone()); + shell.publish(message.get().clone()); return event::Status::Captured; } @@ -415,7 +528,7 @@ fn update( if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) = event { - shell.publish(message.clone()); + shell.publish(message.get().clone()); return event::Status::Captured; } @@ -426,7 +539,7 @@ fn update( mouse::Button::Right, )) = event { - shell.publish(message.clone()); + shell.publish(message.get().clone()); return event::Status::Captured; } @@ -437,7 +550,7 @@ fn update( mouse::Button::Middle, )) = event { - shell.publish(message.clone()); + shell.publish(message.get().clone()); return event::Status::Captured; } @@ -448,7 +561,7 @@ fn update( mouse::Button::Middle, )) = event { - shell.publish(message.clone()); + shell.publish(message.get().clone()); return event::Status::Captured; } From 3a62604d4534dad977efc1005978013d5c77e351 Mon Sep 17 00:00:00 2001 From: Bin Date: Tue, 5 Nov 2024 00:07:22 +0800 Subject: [PATCH 2/2] Add '_with' suffix related methods to MouseArea to support closures --- widget/src/mouse_area.rs | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index cdd29df4db..7ce2ef559b 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -105,10 +105,11 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_double_click_with( - mut self, - on_double_click: impl Fn() -> Message + 'a + mut self, + on_double_click: impl Fn() -> Message + 'a, ) -> Self { - self.on_double_click = Some(OnPress::Closure(Box::new(on_double_click))); + self.on_double_click = + Some(OnPress::Closure(Box::new(on_double_click))); self } @@ -123,7 +124,7 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_right_press_with( - mut self, + mut self, on_right_press: impl Fn() -> Message + 'a, ) -> Self { self.on_right_press = Some(OnPress::Closure(Box::new(on_right_press))); @@ -141,10 +142,11 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_right_release_with( - mut self, - on_right_release: impl Fn() -> Message + 'a + mut self, + on_right_release: impl Fn() -> Message + 'a, ) -> Self { - self.on_right_release = Some(OnPress::Closure(Box::new(on_right_release))); + self.on_right_release = + Some(OnPress::Closure(Box::new(on_right_release))); self } @@ -159,10 +161,11 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_middle_press_with( - mut self, - on_middle_press: impl Fn() -> Message + 'a + mut self, + on_middle_press: impl Fn() -> Message + 'a, ) -> Self { - self.on_middle_press = Some(OnPress::Closure(Box::new(on_middle_press))); + self.on_middle_press = + Some(OnPress::Closure(Box::new(on_middle_press))); self } @@ -177,10 +180,11 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_middle_release_with( - mut self, - on_middle_release: impl Fn() -> Message + 'a + mut self, + on_middle_release: impl Fn() -> Message + 'a, ) -> Self { - self.on_middle_release = Some(OnPress::Closure(Box::new(on_middle_release))); + self.on_middle_release = + Some(OnPress::Closure(Box::new(on_middle_release))); self } @@ -205,8 +209,8 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// the message. #[must_use] pub fn on_enter_with( - mut self, - on_enter: impl Fn() -> Message + 'a + mut self, + on_enter: impl Fn() -> Message + 'a, ) -> Self { self.on_enter = Some(OnPress::Closure(Box::new(on_enter))); self @@ -229,10 +233,7 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> { /// This is analogous to [`MouseArea::on_exit`], but using a closure to produce /// the message. #[must_use] - pub fn on_exit_with( - mut self, - on_exit: impl Fn() -> Message + 'a - ) -> Self { + pub fn on_exit_with(mut self, on_exit: impl Fn() -> Message + 'a) -> Self { self.on_exit = Some(OnPress::Closure(Box::new(on_exit))); self }