summaryrefslogtreecommitdiffstats
path: root/widget/src/toggler.rs
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src/toggler.rs')
-rw-r--r--widget/src/toggler.rs82
1 files changed, 65 insertions, 17 deletions
diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs
index 821e2526..1c425dc1 100644
--- a/widget/src/toggler.rs
+++ b/widget/src/toggler.rs
@@ -26,7 +26,9 @@ use crate::core::{
///
/// let is_toggled = true;
///
-/// Toggler::new(String::from("Toggle me!"), is_toggled, |b| Message::TogglerToggled(b));
+/// Toggler::new(is_toggled)
+/// .label("Toggle me!")
+/// .on_toggle(Message::TogglerToggled);
/// ```
#[allow(missing_debug_implementations)]
pub struct Toggler<
@@ -39,14 +41,15 @@ pub struct Toggler<
Renderer: text::Renderer,
{
is_toggled: bool,
- on_toggle: Box<dyn Fn(bool) -> Message + 'a>,
- label: Option<String>,
+ on_toggle: Option<Box<dyn Fn(bool) -> Message + 'a>>,
+ label: Option<text::Fragment<'a>>,
width: Length,
size: f32,
text_size: Option<Pixels>,
text_line_height: text::LineHeight,
text_alignment: alignment::Horizontal,
text_shaping: text::Shaping,
+ text_wrapping: text::Wrapping,
spacing: f32,
font: Option<Renderer::Font>,
class: Theme::Class<'a>,
@@ -68,30 +71,54 @@ where
/// * a function that will be called when the [`Toggler`] is toggled. It
/// will receive the new state of the [`Toggler`] and must produce a
/// `Message`.
- pub fn new<F>(
- label: impl Into<Option<String>>,
- is_toggled: bool,
- f: F,
- ) -> Self
- where
- F: 'a + Fn(bool) -> Message,
- {
+ pub fn new(is_toggled: bool) -> Self {
Toggler {
is_toggled,
- on_toggle: Box::new(f),
- label: label.into(),
+ on_toggle: None,
+ label: None,
width: Length::Shrink,
size: Self::DEFAULT_SIZE,
text_size: None,
text_line_height: text::LineHeight::default(),
text_alignment: alignment::Horizontal::Left,
- text_shaping: text::Shaping::Basic,
+ text_shaping: text::Shaping::default(),
+ text_wrapping: text::Wrapping::default(),
spacing: Self::DEFAULT_SIZE / 2.0,
font: None,
class: Theme::default(),
}
}
+ /// 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`].
pub fn size(mut self, size: impl Into<Pixels>) -> Self {
self.size = size.into().0;
@@ -131,6 +158,12 @@ where
self
}
+ /// Sets the [`text::Wrapping`] strategy of the [`Toggler`].
+ pub fn text_wrapping(mut self, wrapping: text::Wrapping) -> Self {
+ self.text_wrapping = wrapping;
+ self
+ }
+
/// Sets the spacing between the [`Toggler`] and the text.
pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
self.spacing = spacing.into().0;
@@ -216,6 +249,7 @@ where
self.text_alignment,
alignment::Vertical::Top,
self.text_shaping,
+ self.text_wrapping,
)
} else {
layout::Node::new(Size::ZERO)
@@ -235,13 +269,17 @@ where
shell: &mut Shell<'_, Message>,
_viewport: &Rectangle,
) -> event::Status {
+ let Some(on_toggle) = &self.on_toggle else {
+ return event::Status::Ignored;
+ };
+
match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => {
let mouse_over = cursor.is_over(layout.bounds());
if mouse_over {
- shell.publish((self.on_toggle)(!self.is_toggled));
+ shell.publish(on_toggle(!self.is_toggled));
event::Status::Captured
} else {
@@ -261,7 +299,11 @@ where
_renderer: &Renderer,
) -> mouse::Interaction {
if cursor.is_over(layout.bounds()) {
- mouse::Interaction::Pointer
+ if self.on_toggle.is_some() {
+ mouse::Interaction::Pointer
+ } else {
+ mouse::Interaction::NotAllowed
+ }
} else {
mouse::Interaction::default()
}
@@ -305,7 +347,9 @@ where
let bounds = toggler_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 {
is_toggled: self.is_toggled,
}
@@ -394,6 +438,8 @@ pub enum Status {
/// Indicates whether the [`Toggler`] is toggled.
is_toggled: bool,
},
+ /// The [`Toggler`] is disabled.
+ Disabled,
}
/// The appearance of a toggler.
@@ -454,6 +500,7 @@ pub fn default(theme: &Theme, status: Status) -> Style {
palette.background.strong.color
}
}
+ Status::Disabled => palette.background.weak.color,
};
let foreground = match status {
@@ -474,6 +521,7 @@ pub fn default(theme: &Theme, status: Status) -> Style {
palette.background.weak.color
}
}
+ Status::Disabled => palette.background.base.color,
};
Style {