From b5f1ca169567f47b3976de5b4c5a2b1ce37656d5 Mon Sep 17 00:00:00 2001 From: Alexander van Saase Date: Mon, 2 Oct 2023 20:18:15 +0200 Subject: Introduce support for disabling a `checkbox` --- widget/src/checkbox.rs | 60 ++++++++++++++++++++++++++++++++++++-------------- widget/src/helpers.rs | 3 +-- 2 files changed, 44 insertions(+), 19 deletions(-) (limited to 'widget') diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 6f559ccc..eb1faf5c 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -43,7 +43,7 @@ pub struct Checkbox< Renderer: text::Renderer, { is_checked: bool, - on_toggle: Box Message + 'a>, + on_toggle: Option Message + 'a>>, label: String, width: Length, size: f32, @@ -70,18 +70,12 @@ where /// Creates a new [`Checkbox`]. /// /// It expects: - /// * a boolean describing whether the [`Checkbox`] is checked or not /// * the label of the [`Checkbox`] - /// * a function that will be called when the [`Checkbox`] is toggled. It - /// will receive the new state of the [`Checkbox`] and must produce a - /// `Message`. - pub fn new(label: impl Into, is_checked: bool, f: F) -> Self - where - F: 'a + Fn(bool) -> Message, - { + /// * a boolean describing whether the [`Checkbox`] is checked or not + pub fn new(label: impl Into, is_checked: bool) -> Self { Checkbox { is_checked, - on_toggle: Box::new(f), + on_toggle: None, label: label.into(), width: Length::Shrink, size: Self::DEFAULT_SIZE, @@ -101,6 +95,32 @@ where } } + /// Sets the function that will be called when the [`Checkbox`] is toggled. + /// It will receive the new state of the [`Checkbox`] and must produce a + /// `Message`. + /// + /// Unless `on_toggle` is called, the [`Checkbox`] will be disabled. + pub fn on_toggle(mut self, f: F) -> Self + where + F: 'a + Fn(bool) -> Message, + { + self.on_toggle = Some(Box::new(f)); + self + } + + /// Sets the function that will be called when the [`Checkbox`] is toggled, + /// if `Some`. + /// + /// If `None`, the checkbox will be disabled. + pub fn on_toggle_maybe(mut self, f: Option) -> Self + where + F: Fn(bool) -> Message + 'a, + { + self.on_toggle = + f.map(|f| Box::new(f) as Box Message + 'a>); + self + } + /// Sets the size of the [`Checkbox`]. pub fn size(mut self, size: impl Into) -> Self { self.size = size.into().0; @@ -235,9 +255,10 @@ where let mouse_over = cursor.is_over(layout.bounds()); if mouse_over { - shell.publish((self.on_toggle)(!self.is_checked)); - - return event::Status::Captured; + if let Some(on_toggle) = &self.on_toggle { + shell.publish((on_toggle)(!self.is_checked)); + return event::Status::Captured; + } } } _ => {} @@ -254,7 +275,7 @@ where _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - if cursor.is_over(layout.bounds()) { + if cursor.is_over(layout.bounds()) && self.on_toggle.is_some() { mouse::Interaction::Pointer } else { mouse::Interaction::default() @@ -272,13 +293,18 @@ where viewport: &Rectangle, ) { let is_mouse_over = cursor.is_over(layout.bounds()); + let is_enabled = self.on_toggle.is_some(); let mut children = layout.children(); - let custom_style = if is_mouse_over { - theme.hovered(&self.style, self.is_checked) + let custom_style = if is_enabled { + if is_mouse_over { + theme.hovered(&self.style, self.is_checked) + } else { + theme.active(&self.style, self.is_checked) + } } else { - theme.active(&self.style, self.is_checked) + theme.disabled(&self.style, self.is_checked) }; { diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 444eb4c2..e13e900a 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -158,13 +158,12 @@ where pub fn checkbox<'a, Message, Theme, Renderer>( label: impl Into, is_checked: bool, - f: impl Fn(bool) -> Message + 'a, ) -> Checkbox<'a, Message, Theme, Renderer> where Theme: checkbox::StyleSheet + text::StyleSheet, Renderer: core::text::Renderer, { - Checkbox::new(label, is_checked, f) + Checkbox::new(label, is_checked) } /// Creates a new [`Radio`]. -- cgit