From 495985f449e46b24e6b734d3aa9e135a779a8b77 Mon Sep 17 00:00:00 2001 From: pml68 Date: Sun, 13 Apr 2025 03:40:38 +0200 Subject: refactor: move `material_theme` and `iced_drop` into separate crates dir --- crates/material_theme/src/button.rs | 193 ++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 crates/material_theme/src/button.rs (limited to 'crates/material_theme/src/button.rs') diff --git a/crates/material_theme/src/button.rs b/crates/material_theme/src/button.rs new file mode 100644 index 0000000..21d77b7 --- /dev/null +++ b/crates/material_theme/src/button.rs @@ -0,0 +1,193 @@ +use iced_widget::button::{Catalog, Status, Style, StyleFn}; +use iced_widget::core::{Background, Border, Color, border}; + +use crate::Theme; +use crate::utils::{ + DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, + PRESSED_LAYER_OPACITY, elevation, mix, shadow_from_elevation, +}; + +impl Catalog for Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> Self::Class<'a> { + Box::new(filled) + } + + fn style(&self, class: &Self::Class<'_>, status: Status) -> Style { + class(self, status) + } +} + +fn button( + foreground: Color, + background: Color, + tone_overlay: Color, + disabled: Color, + shadow_color: Color, + elevation_level: u8, + status: Status, +) -> Style { + let active = Style { + background: Some(Background::Color(background)), + text_color: foreground, + border: border::rounded(400), + shadow: shadow_from_elevation(elevation(elevation_level), shadow_color), + }; + + match status { + Status::Active => active, + Status::Pressed => Style { + background: Some(Background::Color(mix( + background, + tone_overlay, + HOVERED_LAYER_OPACITY, + ))), + ..active + }, + Status::Hovered => Style { + background: Some(Background::Color(mix( + background, + tone_overlay, + PRESSED_LAYER_OPACITY, + ))), + text_color: foreground, + border: border::rounded(400), + shadow: shadow_from_elevation( + elevation(elevation_level + 1), + shadow_color, + ), + }, + Status::Disabled => Style { + background: Some(Background::Color(Color { + a: DISABLED_CONTAINER_OPACITY, + ..disabled + })), + text_color: Color { + a: DISABLED_TEXT_OPACITY, + ..disabled + }, + border: border::rounded(400), + ..Default::default() + }, + } +} + +pub fn elevated(theme: &Theme, status: Status) -> Style { + let surface_colors = theme.colorscheme.surface; + + let foreground = theme.colorscheme.primary.color; + let background = surface_colors.surface_container.low; + let disabled = surface_colors.on_surface; + + let shadow_color = theme.colorscheme.shadow; + + button( + foreground, + background, + foreground, + disabled, + shadow_color, + 1, + status, + ) +} + +pub fn filled(theme: &Theme, status: Status) -> Style { + let primary_colors = theme.colorscheme.primary; + + let foreground = primary_colors.on_primary; + let background = primary_colors.color; + let disabled = theme.colorscheme.surface.on_surface; + + let shadow_color = theme.colorscheme.shadow; + + button( + foreground, + background, + foreground, + disabled, + shadow_color, + 0, + status, + ) +} + +pub fn filled_tonal(theme: &Theme, status: Status) -> Style { + let secondary_colors = theme.colorscheme.secondary; + + let foreground = secondary_colors.on_secondary_container; + let background = secondary_colors.secondary_container; + let disabled = theme.colorscheme.surface.on_surface; + let shadow_color = theme.colorscheme.shadow; + + button( + foreground, + background, + foreground, + disabled, + shadow_color, + 0, + status, + ) +} + +pub fn outlined(theme: &Theme, status: Status) -> Style { + let foreground = theme.colorscheme.primary.color; + let background = Color::TRANSPARENT; + let disabled = theme.colorscheme.surface.on_surface; + + let outline = theme.colorscheme.outline.color; + + let border = match status { + Status::Active | Status::Pressed | Status::Hovered => Border { + color: outline, + width: 1.0, + radius: 400.0.into(), + }, + Status::Disabled => Border { + color: Color { + a: DISABLED_CONTAINER_OPACITY, + ..disabled + }, + width: 1.0, + radius: 400.0.into(), + }, + }; + + let style = button( + foreground, + background, + foreground, + disabled, + Color::TRANSPARENT, + 0, + status, + ); + + Style { border, ..style } +} + +pub fn text(theme: &Theme, status: Status) -> Style { + let foreground = theme.colorscheme.primary.color; + let background = Color::TRANSPARENT; + let disabled = theme.colorscheme.surface.on_surface; + + let style = button( + foreground, + background, + foreground, + disabled, + Color::TRANSPARENT, + 0, + status, + ); + + match status { + Status::Hovered | Status::Pressed => style, + _ => Style { + background: None, + ..style + }, + } +} -- cgit v1.2.3 From c3c05cef555de305729e53cef8b8e660e31eaf27 Mon Sep 17 00:00:00 2001 From: pml68 Date: Tue, 22 Apr 2025 14:33:36 +0200 Subject: refactor: apply some clippy suggestions --- Cargo.lock | 99 ++++++++++++++++------------------- crates/material_theme/src/button.rs | 4 +- crates/material_theme/src/checkbox.rs | 6 +-- crates/material_theme/src/lib.rs | 5 +- crates/material_theme/src/utils.rs | 6 ++- src/panes/code_view.rs | 2 +- 6 files changed, 59 insertions(+), 63 deletions(-) (limited to 'crates/material_theme/src/button.rs') diff --git a/Cargo.lock b/Cargo.lock index 4f0a992..fd31403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,11 +534,11 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d59b4c170e16f0405a2e95aff44432a0d41aa97675f3d52623effe95792a037" +checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" dependencies = [ - "objc2 0.6.0", + "objc2 0.6.1", ] [[package]] @@ -1070,9 +1070,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0" dependencies = [ "bitflags 2.9.0", - "block2 0.6.0", + "block2 0.6.1", "libc", - "objc2 0.6.0", + "objc2 0.6.1", +] + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.1", ] [[package]] @@ -1160,20 +1170,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "embed-resource" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379" -dependencies = [ - "cc", - "memchr", - "rustc_version", - "toml", - "vswhom", - "winreg", -] - [[package]] name = "embed-resource" version = "3.0.2" @@ -1997,7 +1993,7 @@ name = "iced_builder" version = "0.1.0" dependencies = [ "dirs-next", - "embed-resource 3.0.2", + "embed-resource", "fxhash", "iced", "iced_anim", @@ -2611,9 +2607,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" [[package]] name = "libredox" @@ -2675,12 +2671,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "lockfree-object-pool" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" - [[package]] name = "log" version = "0.4.27" @@ -3124,9 +3114,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ "objc2-encode", ] @@ -3149,14 +3139,14 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.9.0", - "block2 0.6.0", - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "block2 0.6.1", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] @@ -3197,12 +3187,13 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", + "dispatch2 0.3.0", + "objc2 0.6.1", ] [[package]] @@ -3250,12 +3241,12 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", ] @@ -4035,14 +4026,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d" dependencies = [ "ashpd 0.11.0", - "block2 0.6.0", - "dispatch2", + "block2 0.6.1", + "dispatch2 0.2.0", "js-sys", "log", - "objc2 0.6.0", - "objc2-app-kit 0.3.0", + "objc2 0.6.1", + "objc2-app-kit 0.3.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", + "objc2-foundation 0.3.1", "pollster", "raw-window-handle", "urlencoding", @@ -4383,9 +4374,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -5952,12 +5943,12 @@ checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_exe_info" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0960cd3c8e7c1a55327ac8206395748c8145dc56c524057d1d50ab80300f49f" +checksum = "3a7c2cd292e8e58e012eaf18f18f6b64ef74e0b90677b4f9e1f15bfca24056c7" dependencies = [ "camino", - "embed-resource 2.5.1", + "embed-resource", ] [[package]] @@ -6515,15 +6506,13 @@ dependencies = [ [[package]] name = "zopfli" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" dependencies = [ "bumpalo", "crc32fast", - "lockfree-object-pool", "log", - "once_cell", "simd-adler32", ] diff --git a/crates/material_theme/src/button.rs b/crates/material_theme/src/button.rs index 21d77b7..e1369eb 100644 --- a/crates/material_theme/src/button.rs +++ b/crates/material_theme/src/button.rs @@ -143,7 +143,7 @@ pub fn outlined(theme: &Theme, status: Status) -> Style { Status::Active | Status::Pressed | Status::Hovered => Border { color: outline, width: 1.0, - radius: 400.0.into(), + radius: 400.into(), }, Status::Disabled => Border { color: Color { @@ -151,7 +151,7 @@ pub fn outlined(theme: &Theme, status: Status) -> Style { ..disabled }, width: 1.0, - radius: 400.0.into(), + radius: 400.into(), }, }; diff --git a/crates/material_theme/src/checkbox.rs b/crates/material_theme/src/checkbox.rs index ac1f974..ff038b0 100644 --- a/crates/material_theme/src/checkbox.rs +++ b/crates/material_theme/src/checkbox.rs @@ -18,7 +18,7 @@ impl Catalog for Theme { pub fn styled( background_color: Color, - background_hover: Option, + background_unchecked: Option, icon_color: Color, border_color: Color, text_color: Option, @@ -28,7 +28,7 @@ pub fn styled( background: Background::Color(if is_checked { background_color } else { - background_hover.unwrap_or(Color::TRANSPARENT) + background_unchecked.unwrap_or(Color::TRANSPARENT) }), icon_color, border: if is_checked { @@ -37,7 +37,7 @@ pub fn styled( Border { color: border_color, width: 2.0, - radius: border::radius(2), + radius: 2.into(), } }, text_color, diff --git a/crates/material_theme/src/lib.rs b/crates/material_theme/src/lib.rs index 416c958..13f13b1 100644 --- a/crates/material_theme/src/lib.rs +++ b/crates/material_theme/src/lib.rs @@ -24,6 +24,7 @@ pub mod slider; #[cfg(feature = "svg")] pub mod svg; pub mod text; +pub mod text_editor; pub mod text_input; pub mod toggler; pub mod utils; @@ -59,7 +60,7 @@ impl Clone for Theme { } fn clone_from(&mut self, source: &Self) { - self.name = source.name.clone(); + self.name.clone_from(&source.name); self.colorscheme = source.colorscheme; } } @@ -142,6 +143,7 @@ pub struct ColorScheme { pub scrim: Color, } +#[allow(clippy::cast_precision_loss)] macro_rules! from_argb { ($hex:expr) => {{ let hex = $hex as u32; @@ -155,6 +157,7 @@ macro_rules! from_argb { }}; } +#[allow(clippy::cast_precision_loss)] impl ColorScheme { const DARK: Self = Self { primary: Primary { diff --git a/crates/material_theme/src/utils.rs b/crates/material_theme/src/utils.rs index f35396f..5ad137e 100644 --- a/crates/material_theme/src/utils.rs +++ b/crates/material_theme/src/utils.rs @@ -1,5 +1,7 @@ use iced_widget::core::{Color, Shadow, Vector}; +const COLOR_ERROR_MARGIN: f32 = 0.0001; + pub const HOVERED_LAYER_OPACITY: f32 = 0.08; pub const PRESSED_LAYER_OPACITY: f32 = 0.1; @@ -95,7 +97,9 @@ pub fn mix(color1: Color, color2: Color, p2: f32) -> Color { let p1 = 1.0 - p2; - if color1.a != 1.0 || color2.a != 1.0 { + if (color1.a - 1.0).abs() > COLOR_ERROR_MARGIN + || (color2.a - 1.0) > COLOR_ERROR_MARGIN + { let a = color1.a * p1 + color2.a * p2; if a > 0.0 { let c1 = color1.into_linear().map(|c| c * color1.a * p1); diff --git a/src/panes/code_view.rs b/src/panes/code_view.rs index 85b0bbe..890af8a 100644 --- a/src/panes/code_view.rs +++ b/src/panes/code_view.rs @@ -71,7 +71,7 @@ pub fn view( palette.background.base.color, ), border: Border { - radius: 2.0.into(), + radius: 2.into(), width: 1.0, color: palette.background.strong.color, }, -- cgit v1.2.3 From dac7e82e0bff128097653fe05829b2d576fcdb2f Mon Sep 17 00:00:00 2001 From: pml68 Date: Mon, 28 Apr 2025 10:56:49 +0200 Subject: refactor(material_theme)!: make `Theme` an enum with `Custom` variant --- crates/material_theme/src/button.rs | 103 +++++++++----------------- crates/material_theme/src/checkbox.rs | 30 +++----- crates/material_theme/src/container.rs | 119 ++++++++++++++++++------------ crates/material_theme/src/dialog.rs | 4 +- crates/material_theme/src/image.rs | 8 +- crates/material_theme/src/lib.rs | 111 +++++++++++++++++++--------- crates/material_theme/src/menu.rs | 2 +- crates/material_theme/src/pane_grid.rs | 8 +- crates/material_theme/src/pick_list.rs | 2 +- crates/material_theme/src/progress_bar.rs | 4 +- crates/material_theme/src/qr_code.rs | 2 +- crates/material_theme/src/radio.rs | 11 +-- crates/material_theme/src/rule.rs | 4 +- crates/material_theme/src/scrollable.rs | 33 ++++----- crates/material_theme/src/slider.rs | 6 +- crates/material_theme/src/text.rs | 22 +++--- crates/material_theme/src/text_editor.rs | 38 +++------- crates/material_theme/src/text_input.rs | 38 +++------- crates/material_theme/src/toggler.rs | 28 +++---- crates/material_theme/src/utils.rs | 18 +++++ 20 files changed, 282 insertions(+), 309 deletions(-) (limited to 'crates/material_theme/src/button.rs') diff --git a/crates/material_theme/src/button.rs b/crates/material_theme/src/button.rs index e1369eb..3f16bc7 100644 --- a/crates/material_theme/src/button.rs +++ b/crates/material_theme/src/button.rs @@ -3,8 +3,8 @@ use iced_widget::core::{Background, Border, Color, border}; use crate::Theme; use crate::utils::{ - DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, - PRESSED_LAYER_OPACITY, elevation, mix, shadow_from_elevation, + HOVERED_LAYER_OPACITY, PRESSED_LAYER_OPACITY, disabled_container, + disabled_text, elevation, mix, shadow_from_elevation, }; impl Catalog for Theme { @@ -20,9 +20,8 @@ impl Catalog for Theme { } fn button( - foreground: Color, background: Color, - tone_overlay: Color, + foreground: Color, disabled: Color, shadow_color: Color, elevation_level: u8, @@ -40,7 +39,7 @@ fn button( Status::Pressed => Style { background: Some(Background::Color(mix( background, - tone_overlay, + foreground, HOVERED_LAYER_OPACITY, ))), ..active @@ -48,25 +47,18 @@ fn button( Status::Hovered => Style { background: Some(Background::Color(mix( background, - tone_overlay, + foreground, PRESSED_LAYER_OPACITY, ))), - text_color: foreground, - border: border::rounded(400), shadow: shadow_from_elevation( elevation(elevation_level + 1), shadow_color, ), + ..active }, Status::Disabled => Style { - background: Some(Background::Color(Color { - a: DISABLED_CONTAINER_OPACITY, - ..disabled - })), - text_color: Color { - a: DISABLED_TEXT_OPACITY, - ..disabled - }, + background: Some(Background::Color(disabled_container(disabled))), + text_color: disabled_text(disabled), border: border::rounded(400), ..Default::default() }, @@ -74,70 +66,46 @@ fn button( } pub fn elevated(theme: &Theme, status: Status) -> Style { - let surface_colors = theme.colorscheme.surface; + let surface = theme.colors().surface; - let foreground = theme.colorscheme.primary.color; - let background = surface_colors.surface_container.low; - let disabled = surface_colors.on_surface; + let foreground = theme.colors().primary.color; + let background = surface.surface_container.low; + let disabled = surface.on_surface; - let shadow_color = theme.colorscheme.shadow; + let shadow_color = theme.colors().shadow; - button( - foreground, - background, - foreground, - disabled, - shadow_color, - 1, - status, - ) + button(background, foreground, disabled, shadow_color, 1, status) } pub fn filled(theme: &Theme, status: Status) -> Style { - let primary_colors = theme.colorscheme.primary; + let primary = theme.colors().primary; - let foreground = primary_colors.on_primary; - let background = primary_colors.color; - let disabled = theme.colorscheme.surface.on_surface; + let foreground = primary.on_primary; + let background = primary.color; + let disabled = theme.colors().surface.on_surface; - let shadow_color = theme.colorscheme.shadow; + let shadow_color = theme.colors().shadow; - button( - foreground, - background, - foreground, - disabled, - shadow_color, - 0, - status, - ) + button(background, foreground, disabled, shadow_color, 0, status) } pub fn filled_tonal(theme: &Theme, status: Status) -> Style { - let secondary_colors = theme.colorscheme.secondary; + let secondary = theme.colors().secondary; - let foreground = secondary_colors.on_secondary_container; - let background = secondary_colors.secondary_container; - let disabled = theme.colorscheme.surface.on_surface; - let shadow_color = theme.colorscheme.shadow; + let foreground = secondary.on_secondary_container; + let background = secondary.secondary_container; + let disabled = theme.colors().surface.on_surface; + let shadow_color = theme.colors().shadow; - button( - foreground, - background, - foreground, - disabled, - shadow_color, - 0, - status, - ) + button(background, foreground, disabled, shadow_color, 0, status) } pub fn outlined(theme: &Theme, status: Status) -> Style { - let foreground = theme.colorscheme.primary.color; + let foreground = theme.colors().primary.color; let background = Color::TRANSPARENT; - let disabled = theme.colorscheme.surface.on_surface; + let disabled = theme.colors().surface.on_surface; - let outline = theme.colorscheme.outline.color; + let outline = theme.colors().outline.color; let border = match status { Status::Active | Status::Pressed | Status::Hovered => Border { @@ -146,17 +114,13 @@ pub fn outlined(theme: &Theme, status: Status) -> Style { radius: 400.into(), }, Status::Disabled => Border { - color: Color { - a: DISABLED_CONTAINER_OPACITY, - ..disabled - }, + color: disabled_container(disabled), width: 1.0, radius: 400.into(), }, }; let style = button( - foreground, background, foreground, disabled, @@ -169,12 +133,11 @@ pub fn outlined(theme: &Theme, status: Status) -> Style { } pub fn text(theme: &Theme, status: Status) -> Style { - let foreground = theme.colorscheme.primary.color; + let foreground = theme.colors().primary.color; let background = Color::TRANSPARENT; - let disabled = theme.colorscheme.surface.on_surface; + let disabled = theme.colors().surface.on_surface; let style = button( - foreground, background, foreground, disabled, @@ -185,7 +148,7 @@ pub fn text(theme: &Theme, status: Status) -> Style { match status { Status::Hovered | Status::Pressed => style, - _ => Style { + Status::Active | Status::Disabled => Style { background: None, ..style }, diff --git a/crates/material_theme/src/checkbox.rs b/crates/material_theme/src/checkbox.rs index ff038b0..7a3729c 100644 --- a/crates/material_theme/src/checkbox.rs +++ b/crates/material_theme/src/checkbox.rs @@ -2,7 +2,7 @@ use iced_widget::checkbox::{Catalog, Status, Style, StyleFn}; use iced_widget::core::{Background, Border, Color, border}; use super::Theme; -use crate::utils::{DISABLED_CONTAINER_OPACITY, HOVERED_LAYER_OPACITY, mix}; +use crate::utils::{HOVERED_LAYER_OPACITY, disabled_text, mix}; impl Catalog for Theme { type Class<'a> = StyleFn<'a, Self>; @@ -45,8 +45,8 @@ pub fn styled( } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; match status { Status::Active { is_checked } => styled( @@ -69,16 +69,10 @@ pub fn default(theme: &Theme, status: Status) -> Style { is_checked, ), Status::Disabled { is_checked } => styled( - Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.on_surface - }, + disabled_text(surface.on_surface), None, surface.color, - Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.on_surface - }, + disabled_text(surface.on_surface), Some(surface.on_surface), is_checked, ), @@ -86,8 +80,8 @@ pub fn default(theme: &Theme, status: Status) -> Style { } pub fn error(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let error = theme.colorscheme.error; + let surface = theme.colors().surface; + let error = theme.colors().error; match status { Status::Active { is_checked } => styled( @@ -110,16 +104,10 @@ pub fn error(theme: &Theme, status: Status) -> Style { is_checked, ), Status::Disabled { is_checked } => styled( - Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.on_surface - }, + disabled_text(surface.on_surface), None, surface.color, - Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.on_surface - }, + disabled_text(surface.on_surface), Some(surface.on_surface), is_checked, ), diff --git a/crates/material_theme/src/container.rs b/crates/material_theme/src/container.rs index a14cfd5..5c253ad 100644 --- a/crates/material_theme/src/container.rs +++ b/crates/material_theme/src/container.rs @@ -1,5 +1,5 @@ use iced_widget::container::{Catalog, Style, StyleFn}; -use iced_widget::core::{Background, border}; +use iced_widget::core::{Background, Border, border}; use super::Theme; @@ -23,151 +23,178 @@ pub fn transparent(_theme: &Theme) -> Style { } pub fn primary(theme: &Theme) -> Style { - let colors = theme.colorscheme.primary; + let primary = theme.colors().primary; + Style { - background: Some(Background::Color(colors.color)), - text_color: Some(colors.on_primary), + background: Some(Background::Color(primary.color)), + text_color: Some(primary.on_primary), border: border::rounded(4), ..Style::default() } } pub fn primary_container(theme: &Theme) -> Style { - let colors = theme.colorscheme.primary; + let primary = theme.colors().primary; + Style { - background: Some(Background::Color(colors.primary_container)), - text_color: Some(colors.on_primary_container), + background: Some(Background::Color(primary.primary_container)), + text_color: Some(primary.on_primary_container), border: border::rounded(8), ..Style::default() } } pub fn secondary(theme: &Theme) -> Style { - let colors = theme.colorscheme.secondary; + let secondary = theme.colors().secondary; + Style { - background: Some(Background::Color(colors.color)), - text_color: Some(colors.on_secondary), + background: Some(Background::Color(secondary.color)), + text_color: Some(secondary.on_secondary), border: border::rounded(4), ..Style::default() } } pub fn secondary_container(theme: &Theme) -> Style { - let colors = theme.colorscheme.secondary; + let secondary = theme.colors().secondary; + Style { - background: Some(Background::Color(colors.secondary_container)), - text_color: Some(colors.on_secondary_container), + background: Some(Background::Color(secondary.secondary_container)), + text_color: Some(secondary.on_secondary_container), border: border::rounded(8), ..Style::default() } } pub fn tertiary(theme: &Theme) -> Style { - let colors = theme.colorscheme.tertiary; + let tertiary = theme.colors().tertiary; + Style { - background: Some(Background::Color(colors.color)), - text_color: Some(colors.on_tertiary), + background: Some(Background::Color(tertiary.color)), + text_color: Some(tertiary.on_tertiary), border: border::rounded(4), ..Style::default() } } pub fn tertiary_container(theme: &Theme) -> Style { - let colors = theme.colorscheme.tertiary; + let tertiary = theme.colors().tertiary; + Style { - background: Some(Background::Color(colors.tertiary_container)), - text_color: Some(colors.on_tertiary_container), + background: Some(Background::Color(tertiary.tertiary_container)), + text_color: Some(tertiary.on_tertiary_container), border: border::rounded(8), ..Style::default() } } pub fn error(theme: &Theme) -> Style { - let colors = theme.colorscheme.error; + let error = theme.colors().error; + Style { - background: Some(Background::Color(colors.color)), - text_color: Some(colors.on_error), + background: Some(Background::Color(error.color)), + text_color: Some(error.on_error), border: border::rounded(4), ..Style::default() } } pub fn error_container(theme: &Theme) -> Style { - let colors = theme.colorscheme.error; + let error = theme.colors().error; + Style { - background: Some(Background::Color(colors.error_container)), - text_color: Some(colors.on_error_container), + background: Some(Background::Color(error.error_container)), + text_color: Some(error.on_error_container), border: border::rounded(8), ..Style::default() } } pub fn surface(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.color)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.color)), + text_color: Some(surface.on_surface), border: border::rounded(4), ..Style::default() } } pub fn surface_container_lowest(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.surface_container.lowest)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.surface_container.lowest)), + text_color: Some(surface.on_surface), border: border::rounded(8), ..Style::default() } } pub fn surface_container_low(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.surface_container.low)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.surface_container.low)), + text_color: Some(surface.on_surface), border: border::rounded(8), ..Style::default() } } pub fn surface_container(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.surface_container.base)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.surface_container.base)), + text_color: Some(surface.on_surface), border: border::rounded(8), ..Style::default() } } pub fn surface_container_high(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.surface_container.high)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.surface_container.high)), + text_color: Some(surface.on_surface), border: border::rounded(8), ..Style::default() } } pub fn surface_container_highest(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; + Style { - background: Some(Background::Color(colors.surface_container.highest)), - text_color: Some(colors.on_surface), + background: Some(Background::Color(surface.surface_container.highest)), + text_color: Some(surface.on_surface), border: border::rounded(8), ..Style::default() } } pub fn inverse_surface(theme: &Theme) -> Style { - let colors = theme.colorscheme.inverse; + let inverse = theme.colors().inverse; + Style { - background: Some(Background::Color(colors.inverse_surface)), - text_color: Some(colors.inverse_on_surface), + background: Some(Background::Color(inverse.inverse_surface)), + text_color: Some(inverse.inverse_on_surface), border: border::rounded(4), ..Style::default() } } + +pub fn outlined(theme: &Theme) -> Style { + let base = transparent(theme); + + Style { + border: Border { + color: theme.colors().outline.color, + ..base.border + }, + ..base + } +} diff --git a/crates/material_theme/src/dialog.rs b/crates/material_theme/src/dialog.rs index a022548..c839948 100644 --- a/crates/material_theme/src/dialog.rs +++ b/crates/material_theme/src/dialog.rs @@ -25,7 +25,7 @@ impl Catalog for Theme { } pub fn default_container(theme: &Theme) -> container::Style { - let colors = theme.colorscheme.surface; + let colors = theme.colors().surface; container::Style { background: Some(Background::Color(colors.surface_container.high)), text_color: Some(colors.on_surface_variant), @@ -36,6 +36,6 @@ pub fn default_container(theme: &Theme) -> container::Style { pub fn default(theme: &Theme) -> Style { Style { - backdrop_color: theme.colorscheme.scrim, + backdrop_color: theme.colors().scrim, } } diff --git a/crates/material_theme/src/image.rs b/crates/material_theme/src/image.rs index de5942a..4251b39 100644 --- a/crates/material_theme/src/image.rs +++ b/crates/material_theme/src/image.rs @@ -1,21 +1,15 @@ -use iced_widget::core::{Background, Border, Color, border}; use iced_widget::image::{Catalog, Style, StyleFn}; use super::Theme; -use crate::utils::{elevation, shadow_from_elevation}; impl Catalog for Theme { type Class<'a> = StyleFn<'a, Self>; fn default<'a>() -> Self::Class<'a> { - Box::new(default) + Box::new(|_theme| Style::default()) } fn style(&self, class: &Self::Class<'_>) -> Style { class(self) } } - -pub fn default(_theme: &Theme) -> Style { - Style::default() -} diff --git a/crates/material_theme/src/lib.rs b/crates/material_theme/src/lib.rs index 1b4f90e..7b6ac58 100644 --- a/crates/material_theme/src/lib.rs +++ b/crates/material_theme/src/lib.rs @@ -2,6 +2,7 @@ use std::sync::LazyLock; use iced_widget::core::Color; use iced_widget::core::theme::{Base, Style}; +use utils::{lightness, mix}; pub mod button; pub mod checkbox; @@ -45,31 +46,47 @@ macro_rules! from_argb { }}; } -#[derive(Debug, Clone, Copy, PartialEq)] +#[allow(clippy::large_enum_variant)] +#[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct Theme { - pub name: &'static str, - #[cfg_attr(feature = "serde", serde(flatten))] - pub colorscheme: ColorScheme, +pub enum Theme { + Dark, + Light, + Custom(Custom), } impl Theme { - pub const ALL: &'static [Self] = &[Self::DARK, Self::LIGHT]; - - pub const DARK: Self = Self { - name: "Dark", - colorscheme: ColorScheme::DARK, - }; - - pub const LIGHT: Self = Self { - name: "Light", - colorscheme: ColorScheme::LIGHT, - }; + pub const ALL: &'static [Self] = &[Self::Dark, Self::Light]; pub fn new(name: impl Into, colorscheme: ColorScheme) -> Self { - Self { - name: Box::leak(name.into().into_boxed_str()), + Self::Custom(Custom { + name: name.into(), colorscheme, + is_dark: lightness(colorscheme.surface.color) <= 0.5, + }) + } + + pub fn name(&self) -> &str { + match self { + Self::Dark => "Dark", + Self::Light => "Light", + Self::Custom(custom) => &custom.name, + } + } + + pub fn colors(&self) -> ColorScheme { + match self { + Self::Dark => ColorScheme::DARK, + Self::Light => ColorScheme::LIGHT, + Self::Custom(custom) => custom.colorscheme, + } + } + + pub fn is_dark(&self) -> bool { + match self { + Self::Dark => true, + Self::Light => false, + Self::Custom(custom) => custom.is_dark, } } } @@ -80,43 +97,39 @@ impl Default for Theme { match dark_light::detect().unwrap_or(dark_light::Mode::Unspecified) { dark_light::Mode::Dark | dark_light::Mode::Unspecified => { - Theme::DARK + Theme::Dark } - dark_light::Mode::Light => Theme::LIGHT, + dark_light::Mode::Light => Theme::Light, } }); - *DEFAULT + DEFAULT.clone() } } impl std::fmt::Display for Theme { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.name) + write!(f, "{}", self.name()) } } impl Base for Theme { fn base(&self) -> Style { Style { - background_color: self.colorscheme.surface.color, - text_color: self.colorscheme.surface.on_surface, + background_color: self.colors().surface.color, + text_color: self.colors().surface.on_surface, } } fn palette(&self) -> Option { - let colors = self.colorscheme; + let colors = self.colors(); Some(iced_widget::theme::Palette { background: colors.surface.color, text: colors.surface.on_surface, primary: colors.primary.color, success: colors.primary.primary_container, - warning: utils::mix( - from_argb!(0xffffff00), - colors.primary.color, - 0.25, - ), + warning: mix(from_argb!(0xffffff00), colors.primary.color, 0.25), danger: colors.error.color, }) } @@ -129,18 +142,44 @@ impl iced_anim::Animate for Theme { } fn update(&mut self, components: &mut impl Iterator) { - self.colorscheme.update(components); - self.name = "Animating Theme"; + let mut colorscheme = self.colors(); + colorscheme.update(components); + *self = Self::new("Animating Theme", colorscheme); } fn distance_to(&self, end: &Self) -> Vec { - self.colorscheme.distance_to(&end.colorscheme) + self.colors().distance_to(&end.colors()) } fn lerp(&mut self, start: &Self, end: &Self, progress: f32) { - self.colorscheme - .lerp(&start.colorscheme, &end.colorscheme, progress); - self.name = "Animating Theme"; + let mut colorscheme = self.colors(); + colorscheme.lerp(&start.colors(), &end.colors(), progress); + *self = Self::new("Animating Theme", colorscheme); + } +} + +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Custom { + pub name: String, + #[cfg_attr(feature = "serde", serde(flatten))] + pub colorscheme: ColorScheme, + pub is_dark: bool, +} + +impl Clone for Custom { + fn clone(&self) -> Self { + Self { + name: self.name.clone(), + colorscheme: self.colorscheme, + is_dark: self.is_dark, + } + } + + fn clone_from(&mut self, source: &Self) { + self.name.clone_from(&source.name); + self.colorscheme = source.colorscheme; + self.is_dark = source.is_dark; } } diff --git a/crates/material_theme/src/menu.rs b/crates/material_theme/src/menu.rs index 9f43c72..d595c2f 100644 --- a/crates/material_theme/src/menu.rs +++ b/crates/material_theme/src/menu.rs @@ -17,7 +17,7 @@ impl Catalog for Theme { } pub fn default(theme: &Theme) -> Style { - let colors = theme.colorscheme.surface; + let colors = theme.colors().surface; Style { border: border::rounded(4), diff --git a/crates/material_theme/src/pane_grid.rs b/crates/material_theme/src/pane_grid.rs index d66e475..fb69a32 100644 --- a/crates/material_theme/src/pane_grid.rs +++ b/crates/material_theme/src/pane_grid.rs @@ -20,18 +20,18 @@ pub fn default(theme: &Theme) -> Style { Style { hovered_region: Highlight { background: Background::Color(mix( - theme.colorscheme.tertiary.tertiary_container, - theme.colorscheme.surface.on_surface, + theme.colors().tertiary.tertiary_container, + theme.colors().surface.on_surface, HOVERED_LAYER_OPACITY, )), border: border::rounded(12), }, picked_split: Line { - color: theme.colorscheme.outline.variant, + color: theme.colors().outline.variant, width: 2.0, }, hovered_split: Line { - color: theme.colorscheme.surface.on_surface, + color: theme.colors().surface.on_surface, width: 6.0, }, } diff --git a/crates/material_theme/src/pick_list.rs b/crates/material_theme/src/pick_list.rs index 4b34871..1fe015e 100644 --- a/crates/material_theme/src/pick_list.rs +++ b/crates/material_theme/src/pick_list.rs @@ -20,7 +20,7 @@ impl Catalog for Theme { } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; + let surface = theme.colors().surface; let active = Style { text_color: surface.on_surface, diff --git a/crates/material_theme/src/progress_bar.rs b/crates/material_theme/src/progress_bar.rs index f686fff..9b4e844 100644 --- a/crates/material_theme/src/progress_bar.rs +++ b/crates/material_theme/src/progress_bar.rs @@ -18,9 +18,9 @@ impl Catalog for Theme { pub fn default(theme: &Theme) -> Style { Style { background: Background::Color( - theme.colorscheme.secondary.secondary_container, + theme.colors().secondary.secondary_container, ), - bar: Background::Color(theme.colorscheme.primary.color), + bar: Background::Color(theme.colors().primary.color), border: border::rounded(400), } } diff --git a/crates/material_theme/src/qr_code.rs b/crates/material_theme/src/qr_code.rs index f93fb77..f603440 100644 --- a/crates/material_theme/src/qr_code.rs +++ b/crates/material_theme/src/qr_code.rs @@ -15,7 +15,7 @@ impl Catalog for Theme { } pub fn default(theme: &Theme) -> Style { - let surface = theme.colorscheme.surface; + let surface = theme.colors().surface; Style { cell: surface.on_surface, diff --git a/crates/material_theme/src/radio.rs b/crates/material_theme/src/radio.rs index d249413..7fb7a3f 100644 --- a/crates/material_theme/src/radio.rs +++ b/crates/material_theme/src/radio.rs @@ -2,7 +2,7 @@ use iced_widget::core::{Background, Color}; use iced_widget::radio::{Catalog, Status, Style, StyleFn}; use super::Theme; -use crate::utils::{DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, mix}; +use crate::utils::{HOVERED_LAYER_OPACITY, disabled_text, mix}; impl Catalog for Theme { type Class<'a> = StyleFn<'a, Self>; @@ -17,8 +17,8 @@ impl Catalog for Theme { } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; let active = Style { background: Color::TRANSPARENT.into(), @@ -46,10 +46,7 @@ pub fn default(theme: &Theme, status: Status) -> Style { border_color: if is_selected { mix(primary.color, surface.on_surface, HOVERED_LAYER_OPACITY) } else { - Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - } + disabled_text(surface.on_surface) }, background: Background::Color(if is_selected { Color { diff --git a/crates/material_theme/src/rule.rs b/crates/material_theme/src/rule.rs index e433005..36e4dd4 100644 --- a/crates/material_theme/src/rule.rs +++ b/crates/material_theme/src/rule.rs @@ -17,7 +17,7 @@ impl Catalog for Theme { pub fn inset(theme: &Theme) -> Style { Style { - color: theme.colorscheme.outline.variant, + color: theme.colors().outline.variant, fill_mode: FillMode::Padded(8), width: 1, radius: Radius::default(), @@ -25,7 +25,7 @@ pub fn inset(theme: &Theme) -> Style { } pub fn full_width(theme: &Theme) -> Style { Style { - color: theme.colorscheme.outline.variant, + color: theme.colors().outline.variant, fill_mode: FillMode::Full, width: 1, radius: Radius::default(), diff --git a/crates/material_theme/src/scrollable.rs b/crates/material_theme/src/scrollable.rs index ee739ba..341f047 100644 --- a/crates/material_theme/src/scrollable.rs +++ b/crates/material_theme/src/scrollable.rs @@ -1,4 +1,4 @@ -use iced_widget::core::{Border, Color, border}; +use iced_widget::core::{Background, Border, border}; use iced_widget::scrollable::{ Catalog, Rail, Scroller, Status, Style, StyleFn, }; @@ -7,8 +7,8 @@ use super::Theme; use super::container::surface_container; use super::utils::mix; use crate::utils::{ - DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, - PRESSED_LAYER_OPACITY, + HOVERED_LAYER_OPACITY, PRESSED_LAYER_OPACITY, disabled_container, + disabled_text, }; impl Catalog for Theme { @@ -24,30 +24,23 @@ impl Catalog for Theme { } pub fn default(theme: &Theme, status: Status) -> Style { - let colors = theme.colorscheme.surface; + let surface = theme.colors().surface; let active = Rail { background: None, scroller: Scroller { - color: colors.on_surface, + color: surface.on_surface, border: border::rounded(400), }, border: Border::default(), }; let disabled = Rail { - background: Some( - Color { - a: DISABLED_CONTAINER_OPACITY, - ..colors.on_surface - } - .into(), - ), + background: Some(Background::Color(disabled_container( + surface.on_surface, + ))), scroller: Scroller { - color: Color { - a: DISABLED_TEXT_OPACITY, - ..colors.on_surface - }, + color: disabled_text(surface.on_surface), border: border::rounded(400), }, ..active @@ -86,8 +79,8 @@ pub fn default(theme: &Theme, status: Status) -> Style { let hovered_rail = Rail { scroller: Scroller { color: mix( - colors.on_surface, - colors.color, + surface.on_surface, + surface.color, HOVERED_LAYER_OPACITY, ), border: border::rounded(400), @@ -122,8 +115,8 @@ pub fn default(theme: &Theme, status: Status) -> Style { let dragged_rail = Rail { scroller: Scroller { color: mix( - colors.on_surface, - colors.color, + surface.on_surface, + surface.color, PRESSED_LAYER_OPACITY, ), border: border::rounded(400), diff --git a/crates/material_theme/src/slider.rs b/crates/material_theme/src/slider.rs index 8665459..ae9ee4b 100644 --- a/crates/material_theme/src/slider.rs +++ b/crates/material_theme/src/slider.rs @@ -41,9 +41,9 @@ pub fn styled(left: Color, right: Color, handle_radius: f32) -> Style { } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; - let secondary = theme.colorscheme.secondary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; + let secondary = theme.colors().secondary; match status { Status::Active => { diff --git a/crates/material_theme/src/text.rs b/crates/material_theme/src/text.rs index 10b2e65..8da3cdf 100644 --- a/crates/material_theme/src/text.rs +++ b/crates/material_theme/src/text.rs @@ -21,66 +21,66 @@ pub fn none(_: &Theme) -> Style { pub fn primary(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.primary.on_primary), + color: Some(theme.colors().primary.on_primary), } } pub fn primary_container(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.primary.on_primary_container), + color: Some(theme.colors().primary.on_primary_container), } } pub fn secondary(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.secondary.on_secondary), + color: Some(theme.colors().secondary.on_secondary), } } pub fn secondary_container(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.secondary.on_secondary_container), + color: Some(theme.colors().secondary.on_secondary_container), } } pub fn tertiary(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.tertiary.on_tertiary), + color: Some(theme.colors().tertiary.on_tertiary), } } pub fn tertiary_container(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.tertiary.on_tertiary_container), + color: Some(theme.colors().tertiary.on_tertiary_container), } } pub fn error(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.error.on_error), + color: Some(theme.colors().error.on_error), } } pub fn error_container(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.error.on_error_container), + color: Some(theme.colors().error.on_error_container), } } pub fn surface(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.surface.on_surface), + color: Some(theme.colors().surface.on_surface), } } pub fn surface_variant(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.surface.on_surface_variant), + color: Some(theme.colors().surface.on_surface_variant), } } pub fn inverse_surface(theme: &Theme) -> Style { Style { - color: Some(theme.colorscheme.inverse.inverse_on_surface), + color: Some(theme.colors().inverse.inverse_on_surface), } } diff --git a/crates/material_theme/src/text_editor.rs b/crates/material_theme/src/text_editor.rs index daad7d2..14d7104 100644 --- a/crates/material_theme/src/text_editor.rs +++ b/crates/material_theme/src/text_editor.rs @@ -2,7 +2,7 @@ use iced_widget::core::{Background, Border, Color, border}; use iced_widget::text_editor::{Catalog, Status, Style, StyleFn}; use super::Theme; -use crate::utils::DISABLED_TEXT_OPACITY; +use crate::utils::{disabled_container, disabled_text}; impl Catalog for Theme { type Class<'a> = StyleFn<'a, Self>; @@ -17,23 +17,20 @@ impl Catalog for Theme { } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; let active = Style { background: Background::Color(surface.surface_container.highest), border: Border { - color: theme.colorscheme.outline.color, + color: theme.colors().outline.color, width: 1.0, radius: 4.into(), }, icon: surface.on_surface_variant, placeholder: surface.on_surface_variant, value: surface.on_surface, - selection: Color { - a: DISABLED_TEXT_OPACITY, - ..primary.color - }, + selection: disabled_text(primary.color), }; match status { @@ -57,29 +54,14 @@ pub fn default(theme: &Theme, status: Status) -> Style { Status::Disabled => Style { background: Color::TRANSPARENT.into(), border: Border { - color: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, + color: disabled_container(surface.on_surface), width: 1.0, radius: border::radius(4), }, - icon: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - placeholder: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - selection: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - value: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, + icon: disabled_text(surface.on_surface), + placeholder: disabled_text(surface.on_surface), + value: disabled_text(surface.on_surface), + selection: disabled_text(surface.on_surface), }, } } diff --git a/crates/material_theme/src/text_input.rs b/crates/material_theme/src/text_input.rs index 5de5993..ed5e02a 100644 --- a/crates/material_theme/src/text_input.rs +++ b/crates/material_theme/src/text_input.rs @@ -2,7 +2,7 @@ use iced_widget::core::{Background, Border, Color}; use iced_widget::text_input::{Catalog, Status, Style, StyleFn}; use super::Theme; -use crate::utils::{DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY}; +use crate::utils::{disabled_container, disabled_text}; impl Catalog for Theme { type Class<'a> = StyleFn<'a, Self>; @@ -17,23 +17,20 @@ impl Catalog for Theme { } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; let active = Style { background: Background::Color(surface.surface_container.highest), border: Border { - color: theme.colorscheme.outline.color, + color: theme.colors().outline.color, width: 1.0, radius: 4.into(), }, icon: surface.on_surface_variant, placeholder: surface.on_surface_variant, value: surface.on_surface, - selection: Color { - a: DISABLED_TEXT_OPACITY, - ..primary.color - }, + selection: disabled_text(primary.color), }; match status { @@ -48,28 +45,13 @@ pub fn default(theme: &Theme, status: Status) -> Style { Status::Disabled => Style { background: Color::TRANSPARENT.into(), border: Border { - color: Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.on_surface - }, + color: disabled_container(surface.on_surface), ..active.border }, - icon: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - placeholder: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - value: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - selection: Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, + icon: disabled_text(surface.on_surface), + placeholder: disabled_text(surface.on_surface), + value: disabled_text(surface.on_surface), + selection: disabled_text(surface.on_surface), }, Status::Focused { .. } => Style { border: Border { diff --git a/crates/material_theme/src/toggler.rs b/crates/material_theme/src/toggler.rs index 8949d07..5cebc88 100644 --- a/crates/material_theme/src/toggler.rs +++ b/crates/material_theme/src/toggler.rs @@ -3,8 +3,7 @@ use iced_widget::toggler::{Catalog, Status, Style, StyleFn}; use super::Theme; use crate::utils::{ - DISABLED_CONTAINER_OPACITY, DISABLED_TEXT_OPACITY, HOVERED_LAYER_OPACITY, - mix, + HOVERED_LAYER_OPACITY, disabled_container, disabled_text, mix, }; impl Catalog for Theme { @@ -35,8 +34,8 @@ pub fn styled( } pub fn default(theme: &Theme, status: Status) -> Style { - let surface = theme.colorscheme.surface; - let primary = theme.colorscheme.primary; + let surface = theme.colors().surface; + let primary = theme.colors().primary; match status { Status::Active { is_toggled } => { @@ -45,8 +44,8 @@ pub fn default(theme: &Theme, status: Status) -> Style { } else { styled( surface.surface_container.highest, - theme.colorscheme.outline.color, - Some(theme.colorscheme.outline.color), + theme.colors().outline.color, + Some(theme.colors().outline.color), ) } } @@ -61,23 +60,14 @@ pub fn default(theme: &Theme, status: Status) -> Style { HOVERED_LAYER_OPACITY, ), surface.on_surface_variant, - Some(theme.colorscheme.outline.color), + Some(theme.colors().outline.color), ) } } Status::Disabled => styled( - Color { - a: DISABLED_CONTAINER_OPACITY, - ..surface.surface_container.highest - }, - Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }, - Some(Color { - a: DISABLED_TEXT_OPACITY, - ..surface.on_surface - }), + disabled_container(surface.surface_container.highest), + disabled_text(surface.on_surface), + Some(disabled_text(surface.on_surface)), ), } } diff --git a/crates/material_theme/src/utils.rs b/crates/material_theme/src/utils.rs index 5ad137e..963c9fc 100644 --- a/crates/material_theme/src/utils.rs +++ b/crates/material_theme/src/utils.rs @@ -30,6 +30,20 @@ pub fn shadow_from_elevation(elevation: f32, color: Color) -> Shadow { } } +pub fn disabled_text(color: Color) -> Color { + Color { + a: DISABLED_TEXT_OPACITY, + ..color + } +} + +pub fn disabled_container(color: Color) -> Color { + Color { + a: DISABLED_CONTAINER_OPACITY, + ..color + } +} + pub fn parse_argb(s: &str) -> Option { let hex = s.strip_prefix('#').unwrap_or(s); @@ -88,6 +102,10 @@ pub fn color_to_argb(color: Color) -> String { hex } +pub const fn lightness(color: Color) -> f32 { + color.r * 0.299 + color.g * 0.587 + color.b * 0.114 +} + pub fn mix(color1: Color, color2: Color, p2: f32) -> Color { if p2 <= 0.0 { return color1; -- cgit v1.2.3