summaryrefslogtreecommitdiffstats
path: root/widget/src/button.rs
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src/button.rs')
-rw-r--r--widget/src/button.rs48
1 files changed, 40 insertions, 8 deletions
diff --git a/widget/src/button.rs b/widget/src/button.rs
index 5d446fea..eafa71b9 100644
--- a/widget/src/button.rs
+++ b/widget/src/button.rs
@@ -1,4 +1,5 @@
//! Allow your users to perform actions by pressing a button.
+use crate::core::border::{self, Border};
use crate::core::event::{self, Event};
use crate::core::layout;
use crate::core::mouse;
@@ -9,8 +10,8 @@ use crate::core::touch;
use crate::core::widget::tree::{self, Tree};
use crate::core::widget::Operation;
use crate::core::{
- Background, Border, Clipboard, Color, Element, Layout, Length, Padding,
- Rectangle, Shadow, Shell, Size, Theme, Vector, Widget,
+ Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle,
+ Shadow, Shell, Size, Theme, Vector, Widget,
};
/// A generic widget that produces a message when pressed.
@@ -52,7 +53,7 @@ where
Theme: Catalog,
{
content: Element<'a, Message, Theme, Renderer>,
- on_press: Option<Message>,
+ on_press: Option<OnPress<'a, Message>>,
width: Length,
height: Length,
padding: Padding,
@@ -60,6 +61,20 @@ where
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>
where
Renderer: crate::core::Renderer,
@@ -105,7 +120,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 +145,7 @@ where
///
/// If `None`, the [`Button`] will be disabled.
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
}
@@ -205,7 +236,7 @@ where
tree: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
- operation: &mut dyn Operation<()>,
+ operation: &mut dyn Operation,
) {
operation.container(None, layout.bounds(), &mut |operation| {
self.content.as_widget().operate(
@@ -258,7 +289,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::<State>();
if state.is_pressed {
@@ -560,7 +592,7 @@ fn styled(pair: palette::Pair) -> Style {
Style {
background: Some(Background::Color(pair.color)),
text_color: pair.text,
- border: Border::rounded(2),
+ border: border::rounded(2),
..Style::default()
}
}