diff options
| -rw-r--r-- | crates/material_theme/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/material_theme/src/toggler.rs | 80 | ||||
| -rw-r--r-- | theme_test/src/main.rs | 17 |
3 files changed, 92 insertions, 6 deletions
diff --git a/crates/material_theme/src/lib.rs b/crates/material_theme/src/lib.rs index 2452d88..0df5b1c 100644 --- a/crates/material_theme/src/lib.rs +++ b/crates/material_theme/src/lib.rs @@ -24,6 +24,7 @@ pub mod slider; pub mod svg; pub mod text; pub mod text_input; +pub mod toggler; pub mod utils; pub static DARK: LazyLock<Theme> = diff --git a/crates/material_theme/src/toggler.rs b/crates/material_theme/src/toggler.rs new file mode 100644 index 0000000..1cc5082 --- /dev/null +++ b/crates/material_theme/src/toggler.rs @@ -0,0 +1,80 @@ +use iced_widget::core::Color; +use iced_widget::toggler::{Catalog, Status, Style, StyleFn}; + +use super::Theme; +use crate::utils::{ + DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, + mix, +}; + +impl Catalog for Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> Self::Class<'a> { + Box::new(default) + } + + fn style(&self, class: &Self::Class<'_>, status: Status) -> Style { + class(self, status) + } +} + +pub fn styled( + background: Color, + foreground: Color, + border: Option<Color>, +) -> Style { + Style { + background, + background_border_width: if border.is_some() { 2.0 } else { 0.0 }, + background_border_color: border.unwrap_or(Color::TRANSPARENT), + foreground, + foreground_border_width: 0.0, + foreground_border_color: Color::TRANSPARENT, + } +} + +pub fn default(theme: &Theme, status: Status) -> Style { + let surface = theme.colorscheme.surface; + let primary = theme.colorscheme.primary; + + match status { + Status::Active { is_toggled } => { + if is_toggled { + styled(primary.color, primary.on_primary, None) + } else { + styled( + surface.surface_container.highest, + theme.colorscheme.outline.color, + Some(theme.colorscheme.outline.color), + ) + } + } + Status::Hovered { is_toggled } => { + if is_toggled { + styled(primary.color, primary.primary_container, None) + } else { + styled( + mix( + surface.surface_container.highest, + surface.on_surface, + HOVERED_LAYER_OPACITY, + ), + surface.on_surface_variant, + Some(theme.colorscheme.outline.color), + ) + } + } + Status::Disabled => styled( + Color { + a: DISABLED_CONTAINER_OPACITY, + ..surface.surface_container.highest + }, + Color { + a: DISABLED_TEXT_OPACITY, + ..surface.on_surface + }, + Some(surface.on_surface), + ), + } +} diff --git a/theme_test/src/main.rs b/theme_test/src/main.rs index 7192785..d564ee5 100644 --- a/theme_test/src/main.rs +++ b/theme_test/src/main.rs @@ -1,7 +1,7 @@ use iced::Length::Fill; use iced::widget::{ button, center, checkbox, column, container, horizontal_rule, pick_list, - radio, row, slider, text_input, + radio, row, slider, text_input, toggler, }; use iced::{Element, Length}; use iced_anim::{Animated, Animation, Event}; @@ -29,7 +29,7 @@ enum Message { OpenDialog, CloseDialog, Input(String), - CheckBox(bool), + Bool(bool), Radio(Choice), Slider(f32), SwitchTheme(Event<Theme>), @@ -63,7 +63,7 @@ impl State { self.show_dialog = false; } Message::Input(content) => self.content = content, - Message::CheckBox(is_checked) => self.is_checked = is_checked, + Message::Bool(is_checked) => self.is_checked = is_checked, Message::Radio(choice) => self.selection = Some(choice), Message::Slider(value) => self.value = value, Message::SwitchTheme(event) => { @@ -149,9 +149,9 @@ impl State { horizontal_rule(1), // Checkbox checkbox("Normal", self.is_checked) - .on_toggle(Message::CheckBox), + .on_toggle(Message::Bool), checkbox("Error", self.is_checked) - .on_toggle(Message::CheckBox) + .on_toggle(Message::Bool) .style(material_theme::checkbox::error), checkbox("Disabled", self.is_checked), horizontal_rule(1), @@ -164,7 +164,12 @@ impl State { center(iced::widget::text!("{:.1}", self.value)) .width(Length::Fill) .height(Length::Shrink), - slider(0.0..=100.0, self.value, Message::Slider).step(0.1) + slider(0.0..=100.0, self.value, Message::Slider).step(0.1), + horizontal_rule(1), + // Toggler + toggler(self.is_checked) + .on_toggle(Message::Bool) + .size(24.0) ] .spacing(10) ] |
