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.
This commit is contained in:
Héctor Ramón Jiménez 2024-07-12 12:08:35 +02:00
parent 1c1bee6fd8
commit 97e35f7d37
No known key found for this signature in database
GPG key ID: 7CC46565708259A7

View file

@ -52,7 +52,7 @@ where
Theme: Catalog, Theme: Catalog,
{ {
content: Element<'a, Message, Theme, Renderer>, content: Element<'a, Message, Theme, Renderer>,
on_press: Option<Message>, on_press: Option<OnPress<'a, Message>>,
width: Length, width: Length,
height: Length, height: Length,
padding: Padding, padding: Padding,
@ -60,6 +60,20 @@ where
class: Theme::Class<'a>, class: Theme::Class<'a>,
} }
enum OnPress<'a, Message> {
Direct(Message),
Closure(Box<dyn Fn() -> 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> impl<'a, Message, Theme, Renderer> Button<'a, Message, Theme, Renderer>
where where
Renderer: crate::core::Renderer, Renderer: crate::core::Renderer,
@ -105,7 +119,23 @@ where
/// ///
/// Unless `on_press` is called, the [`Button`] will be disabled. /// Unless `on_press` is called, the [`Button`] will be disabled.
pub fn on_press(mut self, on_press: Message) -> Self { 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 self
} }
@ -114,7 +144,7 @@ where
/// ///
/// If `None`, the [`Button`] will be disabled. /// If `None`, the [`Button`] will be disabled.
pub fn on_press_maybe(mut self, on_press: Option<Message>) -> Self { pub fn on_press_maybe(mut self, on_press: Option<Message>) -> Self {
self.on_press = on_press; self.on_press = on_press.map(OnPress::Direct);
self self
} }
@ -258,7 +288,8 @@ where
} }
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
| Event::Touch(touch::Event::FingerLifted { .. }) => { | 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::<State>(); let state = tree.state.downcast_mut::<State>();
if state.is_pressed { if state.is_pressed {