From 97e35f7d37ed857fba9b8d831c82b2cc8cf7b31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Fri, 12 Jul 2024 12:08:35 +0200 Subject: [PATCH] Add `on_press_with` method for `Button` This allows using a closure to produce the message only when the `Button` is actually pressed. Useful when generating the message may be expensive. --- widget/src/button.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/widget/src/button.rs b/widget/src/button.rs index 5d446fea37..fb505d6e13 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -52,7 +52,7 @@ where Theme: Catalog, { content: Element<'a, Message, Theme, Renderer>, - on_press: Option, + on_press: Option>, width: Length, height: Length, padding: Padding, @@ -60,6 +60,20 @@ where class: Theme::Class<'a>, } +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> Button<'a, Message, Theme, Renderer> where Renderer: crate::core::Renderer, @@ -105,7 +119,23 @@ where /// /// Unless `on_press` is called, the [`Button`] will be disabled. pub fn on_press(mut self, on_press: Message) -> Self { - self.on_press = Some(on_press); + self.on_press = Some(OnPress::Direct(on_press)); + self + } + + /// Sets the message that will be produced when the [`Button`] is pressed. + /// + /// This is analogous to [`Button::on_press`], but using a closure to produce + /// the message. + /// + /// This closure will only be called when the [`Button`] is actually pressed and, + /// therefore, this method is useful to reduce overhead if creating the resulting + /// message is slow. + 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 } @@ -114,7 +144,7 @@ where /// /// If `None`, the [`Button`] will be disabled. pub fn on_press_maybe(mut self, on_press: Option) -> Self { - self.on_press = on_press; + self.on_press = on_press.map(OnPress::Direct); self } @@ -258,7 +288,8 @@ where } Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) | Event::Touch(touch::Event::FingerLifted { .. }) => { - if let Some(on_press) = self.on_press.clone() { + if let Some(on_press) = self.on_press.as_ref().map(OnPress::get) + { let state = tree.state.downcast_mut::(); if state.is_pressed {