Merge pull request #2478 from sundaram123krishnan/master

Add Disable Feature to Toggler Widget
This commit is contained in:
Héctor Ramón 2024-09-11 00:30:56 +02:00 committed by GitHub
commit 07c9a2a8a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 67 additions and 34 deletions

View file

@ -150,11 +150,9 @@ impl Editor {
self.is_dirty.then_some(Message::SaveFile) self.is_dirty.then_some(Message::SaveFile)
), ),
horizontal_space(), horizontal_space(),
toggler( toggler(self.word_wrap)
Some("Word Wrap"), .label("Word Wrap")
self.word_wrap, .on_toggle(Message::WordWrapToggled),
Message::WordWrapToggled
),
pick_list( pick_list(
highlighter::Theme::ALL, highlighter::Theme::ALL,
Some(self.theme), Some(self.theme),

View file

@ -77,12 +77,10 @@ impl Styling {
let checkbox = checkbox("Check me!", self.checkbox_value) let checkbox = checkbox("Check me!", self.checkbox_value)
.on_toggle(Message::CheckboxToggled); .on_toggle(Message::CheckboxToggled);
let toggler = toggler( let toggler = toggler(self.toggler_value)
Some("Toggle me!"), .label("Toggle me!")
self.toggler_value, .on_toggle(Message::TogglerToggled)
Message::TogglerToggled, .spacing(10);
)
.spacing(10);
let content = column![ let content = column![
choose_theme, choose_theme,

View file

@ -357,11 +357,11 @@ impl Tour {
Self::container("Toggler") Self::container("Toggler")
.push("A toggler is mostly used to enable or disable something.") .push("A toggler is mostly used to enable or disable something.")
.push( .push(
Container::new(toggler( Container::new(
Some("Toggle me to continue..."), toggler(self.toggler)
self.toggler, .label("Toggle me to continue...")
Message::TogglerChanged, .on_toggle(Message::TogglerChanged),
)) )
.padding([0, 40]), .padding([0, 40]),
) )
} }

View file

@ -767,15 +767,13 @@ where
/// ///
/// [`Toggler`]: crate::Toggler /// [`Toggler`]: crate::Toggler
pub fn toggler<'a, Message, Theme, Renderer>( pub fn toggler<'a, Message, Theme, Renderer>(
label: Option<impl text::IntoFragment<'a>>,
is_checked: bool, is_checked: bool,
f: impl Fn(bool) -> Message + 'a,
) -> Toggler<'a, Message, Theme, Renderer> ) -> Toggler<'a, Message, Theme, Renderer>
where where
Theme: toggler::Catalog + 'a, Theme: toggler::Catalog + 'a,
Renderer: core::text::Renderer, Renderer: core::text::Renderer,
{ {
Toggler::new(label, is_checked, f) Toggler::new(is_checked)
} }
/// Creates a new [`TextInput`]. /// Creates a new [`TextInput`].

View file

@ -26,7 +26,9 @@ use crate::core::{
/// ///
/// let is_toggled = true; /// let is_toggled = true;
/// ///
/// Toggler::new(Some("Toggle me!"), is_toggled, |b| Message::TogglerToggled(b)); /// Toggler::new(is_toggled)
/// .label("Toggle me!")
/// .on_toggle(Message::TogglerToggled);
/// ``` /// ```
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Toggler< pub struct Toggler<
@ -39,7 +41,7 @@ pub struct Toggler<
Renderer: text::Renderer, Renderer: text::Renderer,
{ {
is_toggled: bool, is_toggled: bool,
on_toggle: Box<dyn Fn(bool) -> Message + 'a>, on_toggle: Option<Box<dyn Fn(bool) -> Message + 'a>>,
label: Option<text::Fragment<'a>>, label: Option<text::Fragment<'a>>,
width: Length, width: Length,
size: f32, size: f32,
@ -69,18 +71,11 @@ where
/// * a function that will be called when the [`Toggler`] is toggled. It /// * a function that will be called when the [`Toggler`] is toggled. It
/// will receive the new state of the [`Toggler`] and must produce a /// will receive the new state of the [`Toggler`] and must produce a
/// `Message`. /// `Message`.
pub fn new<F>( pub fn new(is_toggled: bool) -> Self {
label: Option<impl text::IntoFragment<'a>>,
is_toggled: bool,
f: F,
) -> Self
where
F: 'a + Fn(bool) -> Message,
{
Toggler { Toggler {
is_toggled, is_toggled,
on_toggle: Box::new(f), on_toggle: None,
label: label.map(text::IntoFragment::into_fragment), label: None,
width: Length::Shrink, width: Length::Shrink,
size: Self::DEFAULT_SIZE, size: Self::DEFAULT_SIZE,
text_size: None, text_size: None,
@ -94,6 +89,36 @@ where
} }
} }
/// Sets the label of the [`Toggler`].
pub fn label(mut self, label: impl text::IntoFragment<'a>) -> Self {
self.label = Some(label.into_fragment());
self
}
/// Sets the message that should be produced when a user toggles
/// the [`Toggler`].
///
/// If this method is not called, the [`Toggler`] will be disabled.
pub fn on_toggle(
mut self,
on_toggle: impl Fn(bool) -> Message + 'a,
) -> Self {
self.on_toggle = Some(Box::new(on_toggle));
self
}
/// Sets the message that should be produced when a user toggles
/// the [`Toggler`], if `Some`.
///
/// If `None`, the [`Toggler`] will be disabled.
pub fn on_toggle_maybe(
mut self,
on_toggle: Option<impl Fn(bool) -> Message + 'a>,
) -> Self {
self.on_toggle = on_toggle.map(|on_toggle| Box::new(on_toggle) as _);
self
}
/// Sets the size of the [`Toggler`]. /// Sets the size of the [`Toggler`].
pub fn size(mut self, size: impl Into<Pixels>) -> Self { pub fn size(mut self, size: impl Into<Pixels>) -> Self {
self.size = size.into().0; self.size = size.into().0;
@ -244,13 +269,17 @@ where
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
_viewport: &Rectangle, _viewport: &Rectangle,
) -> event::Status { ) -> event::Status {
let Some(on_toggle) = &self.on_toggle else {
return event::Status::Ignored;
};
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let mouse_over = cursor.is_over(layout.bounds()); let mouse_over = cursor.is_over(layout.bounds());
if mouse_over { if mouse_over {
shell.publish((self.on_toggle)(!self.is_toggled)); shell.publish(on_toggle(!self.is_toggled));
event::Status::Captured event::Status::Captured
} else { } else {
@ -270,7 +299,11 @@ where
_renderer: &Renderer, _renderer: &Renderer,
) -> mouse::Interaction { ) -> mouse::Interaction {
if cursor.is_over(layout.bounds()) { if cursor.is_over(layout.bounds()) {
mouse::Interaction::Pointer if self.on_toggle.is_some() {
mouse::Interaction::Pointer
} else {
mouse::Interaction::NotAllowed
}
} else { } else {
mouse::Interaction::default() mouse::Interaction::default()
} }
@ -314,7 +347,9 @@ where
let bounds = toggler_layout.bounds(); let bounds = toggler_layout.bounds();
let is_mouse_over = cursor.is_over(layout.bounds()); let is_mouse_over = cursor.is_over(layout.bounds());
let status = if is_mouse_over { let status = if self.on_toggle.is_none() {
Status::Disabled
} else if is_mouse_over {
Status::Hovered { Status::Hovered {
is_toggled: self.is_toggled, is_toggled: self.is_toggled,
} }
@ -403,6 +438,8 @@ pub enum Status {
/// Indicates whether the [`Toggler`] is toggled. /// Indicates whether the [`Toggler`] is toggled.
is_toggled: bool, is_toggled: bool,
}, },
/// The [`Toggler`] is disabled.
Disabled,
} }
/// The appearance of a toggler. /// The appearance of a toggler.
@ -463,6 +500,7 @@ pub fn default(theme: &Theme, status: Status) -> Style {
palette.background.strong.color palette.background.strong.color
} }
} }
Status::Disabled => palette.background.weak.color,
}; };
let foreground = match status { let foreground = match status {
@ -483,6 +521,7 @@ pub fn default(theme: &Theme, status: Status) -> Style {
palette.background.weak.color palette.background.weak.color
} }
} }
Status::Disabled => palette.background.base.color,
}; };
Style { Style {