From ce62ff16fbd8e839b5f707f8d9637db083945803 Mon Sep 17 00:00:00 2001 From: pml68 Date: Thu, 17 Apr 2025 03:00:52 +0200 Subject: refactor: inline Dark and Light theme definitions, remove toml files --- crates/material_theme/src/lib.rs | 238 ++++++++++++++++++++++++++++--------- crates/material_theme/src/utils.rs | 20 ++++ 2 files changed, 202 insertions(+), 56 deletions(-) (limited to 'crates/material_theme/src') diff --git a/crates/material_theme/src/lib.rs b/crates/material_theme/src/lib.rs index cbebdc9..a9beb2a 100644 --- a/crates/material_theme/src/lib.rs +++ b/crates/material_theme/src/lib.rs @@ -1,8 +1,7 @@ use std::sync::LazyLock; -use iced_widget::core::Color; use iced_widget::core::theme::{Base, Style}; -use serde::Deserialize; +use iced_widget::core::{Color, color}; pub mod button; pub mod checkbox; @@ -25,13 +24,16 @@ pub mod text; pub mod text_input; pub mod utils; -const DARK_THEME_CONTENT: &str = include_str!("../assets/themes/dark.toml"); -const LIGHT_THEME_CONTENT: &str = include_str!("../assets/themes/light.toml"); +pub static DARK: LazyLock = + LazyLock::new(|| Theme::new("Dark", ColorScheme::DARK)); +pub static LIGHT: LazyLock = + LazyLock::new(|| Theme::new("Light", ColorScheme::LIGHT)); -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Theme { pub name: String, - #[serde(flatten)] + #[cfg_attr(feature = "serde", serde(flatten))] pub colorscheme: ColorScheme, } @@ -119,16 +121,9 @@ impl iced_anim::Animate for Theme { } } -pub static DARK: LazyLock = LazyLock::new(|| { - toml::from_str(DARK_THEME_CONTENT).expect("parse dark theme") -}); - -pub static LIGHT: LazyLock = LazyLock::new(|| { - toml::from_str(LIGHT_THEME_CONTENT).expect("parse light theme") -}); - -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ColorScheme { pub primary: Primary, pub secondary: Secondary, @@ -137,116 +132,240 @@ pub struct ColorScheme { pub surface: Surface, pub inverse: Inverse, pub outline: Outline, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub shadow: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub scrim: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +macro_rules! from_argb { + ($hex:expr) => {{ + let hex = $hex as u32; + + let a = ((hex & 0xff000000) >> 24) as f32 / 255.0; + let r = (hex & 0x00ff0000) >> 16; + let g = (hex & 0x0000ff00) >> 8; + let b = (hex & 0x000000ff); + + color!(r as u8, g as u8, b as u8, a) + }}; +} + +impl ColorScheme { + const DARK: Self = Self { + primary: Primary { + color: from_argb!(0xff9bd4a1), + on_primary: from_argb!(0xff003916), + primary_container: from_argb!(0xff1b5129), + on_primary_container: from_argb!(0xffb6f1bb), + }, + secondary: Secondary { + color: from_argb!(0xffb8ccb6), + on_secondary: from_argb!(0xff233425), + secondary_container: from_argb!(0xff394b3a), + on_secondary_container: from_argb!(0xffd3e8d1), + }, + tertiary: Tertiary { + color: from_argb!(0xffa1ced7), + on_tertiary: from_argb!(0xff00363e), + tertiary_container: from_argb!(0xff1f4d55), + on_tertiary_container: from_argb!(0xffbdeaf4), + }, + error: Error { + color: from_argb!(0xffffb4ab), + on_error: from_argb!(0xff690005), + error_container: from_argb!(0xff93000a), + on_error_container: from_argb!(0xffffdad6), + }, + surface: Surface { + color: from_argb!(0xff101510), + on_surface: from_argb!(0xffe0e4dc), + on_surface_variant: from_argb!(0xffc1c9be), + surface_container: SurfaceContainer { + lowest: from_argb!(0xff0b0f0b), + low: from_argb!(0xff181d18), + base: from_argb!(0xff1c211c), + high: from_argb!(0xff262b26), + highest: from_argb!(0xff313631), + }, + }, + inverse: Inverse { + inverse_surface: from_argb!(0xffe0e4dc), + inverse_on_surface: from_argb!(0xff2d322c), + inverse_primary: from_argb!(0xff34693f), + }, + outline: Outline { + color: from_argb!(0xff8b9389), + variant: from_argb!(0xff414941), + }, + shadow: from_argb!(0xff000000), + scrim: from_argb!(0x4d000000), + }; + + const LIGHT: Self = Self { + primary: Primary { + color: from_argb!(0xff34693f), + on_primary: from_argb!(0xffffffff), + primary_container: from_argb!(0xffb6f1bb), + on_primary_container: from_argb!(0xff1b5129), + }, + secondary: Secondary { + color: from_argb!(0xff516351), + on_secondary: from_argb!(0xffffffff), + secondary_container: from_argb!(0xffd3e8d1), + on_secondary_container: from_argb!(0xff394b3a), + }, + tertiary: Tertiary { + color: from_argb!(0xff39656d), + on_tertiary: from_argb!(0xffffffff), + tertiary_container: from_argb!(0xffbdeaf4), + on_tertiary_container: from_argb!(0xff1f4d55), + }, + error: Error { + color: from_argb!(0xffba1a1a), + on_error: from_argb!(0xffffffff), + error_container: from_argb!(0xffffdad6), + on_error_container: from_argb!(0xff93000a), + }, + surface: Surface { + color: from_argb!(0xfff7fbf2), + on_surface: from_argb!(0xff181d18), + on_surface_variant: from_argb!(0xff414941), + surface_container: SurfaceContainer { + lowest: from_argb!(0xffffffff), + low: from_argb!(0xfff1f5ed), + base: from_argb!(0xffebefe7), + high: from_argb!(0xffe5e9e1), + highest: from_argb!(0xffe0e4dc), + }, + }, + inverse: Inverse { + inverse_surface: from_argb!(0xff2d322c), + inverse_on_surface: from_argb!(0xffeef2ea), + inverse_primary: from_argb!(0xff9bd4a1), + }, + outline: Outline { + color: from_argb!(0xff727970), + variant: from_argb!(0xffc1c9be), + }, + shadow: from_argb!(0xff000000), + scrim: from_argb!(0x4d000000), + }; +} + +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Primary { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_primary: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub primary_container: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_primary_container: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Secondary { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_secondary: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub secondary_container: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_secondary_container: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Tertiary { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_tertiary: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub tertiary_container: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_tertiary_container: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Error { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_error: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub error_container: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_error_container: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Surface { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_surface: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub on_surface_variant: Color, pub surface_container: SurfaceContainer, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SurfaceContainer { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub lowest: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub low: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub base: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub high: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub highest: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Inverse { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub inverse_surface: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub inverse_on_surface: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub inverse_primary: Color, } -#[derive(Debug, Clone, Copy, PartialEq, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "animate", derive(iced_anim::Animate))] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Outline { - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub color: Color, - #[serde(with = "color_serde")] + #[cfg_attr(feature = "serde", serde(with = "color_serde"))] pub variant: Color, } +#[cfg(feature = "serde")] mod color_serde { use iced_widget::core::Color; - use serde::{Deserialize, Deserializer}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use super::utils::parse_argb; + use super::utils::{color_to_argb, parse_argb}; pub fn deserialize<'de, D>(deserializer: D) -> Result where @@ -256,4 +375,11 @@ mod color_serde { .map(|hex| parse_argb(&hex))? .unwrap_or(Color::TRANSPARENT)) } + + pub fn serialize(color: &Color, serializer: S) -> Result + where + S: Serializer, + { + color_to_argb(*color).serialize(serializer) + } } diff --git a/crates/material_theme/src/utils.rs b/crates/material_theme/src/utils.rs index a05bc62..f35396f 100644 --- a/crates/material_theme/src/utils.rs +++ b/crates/material_theme/src/utils.rs @@ -66,6 +66,26 @@ pub fn parse_argb(s: &str) -> Option { }) } +pub fn color_to_argb(color: Color) -> String { + use std::fmt::Write; + + let mut hex = String::with_capacity(9); + + let [r, g, b, a] = color.into_rgba8(); + + let _ = write!(&mut hex, "#"); + + if a < u8::MAX { + let _ = write!(&mut hex, "{a:02X}"); + } + + let _ = write!(&mut hex, "{r:02X}"); + let _ = write!(&mut hex, "{g:02X}"); + let _ = write!(&mut hex, "{b:02X}"); + + hex +} + pub fn mix(color1: Color, color2: Color, p2: f32) -> Color { if p2 <= 0.0 { return color1; -- cgit v1.2.3