summaryrefslogtreecommitdiff
path: root/crates/material_theme
diff options
context:
space:
mode:
authorpml68 <contact@pml68.dev>2025-04-17 03:00:52 +0200
committerpml68 <contact@pml68.dev>2025-04-17 03:06:43 +0200
commitce62ff16fbd8e839b5f707f8d9637db083945803 (patch)
tree8d7651817fbf17b24f4baae9cc72c83fd224ca71 /crates/material_theme
parentfeat(material_theme): implement `radio::Catalog` (diff)
downloadiced-builder-ce62ff16fbd8e839b5f707f8d9637db083945803.tar.gz
refactor: inline Dark and Light theme definitions, remove toml files
Diffstat (limited to '')
-rw-r--r--crates/material_theme/Cargo.toml8
-rw-r--r--crates/material_theme/assets/themes/dark.toml49
-rw-r--r--crates/material_theme/assets/themes/light.toml49
-rw-r--r--crates/material_theme/src/lib.rs238
-rw-r--r--crates/material_theme/src/utils.rs20
5 files changed, 208 insertions, 156 deletions
diff --git a/crates/material_theme/Cargo.toml b/crates/material_theme/Cargo.toml
index e1da2fb..941bc3e 100644
--- a/crates/material_theme/Cargo.toml
+++ b/crates/material_theme/Cargo.toml
@@ -13,6 +13,8 @@ rust-version = "1.85"
[features]
default = []
+# Provides `serde` support
+serde = ["dep:serde"]
# Provides support for animating with `iced_anim`.
animate = ["dep:iced_anim"]
# Provides support for `iced_dialog`.
@@ -26,9 +28,11 @@ qr_code = ["iced_widget/qr_code"]
[dependencies]
iced_widget = "0.14.0-dev"
-serde.workspace = true
-toml.workspace = true
dark-light = "2.0.0"
+
+serde.workspace = true
+serde.optional = true
+
iced_dialog.workspace = true
iced_dialog.optional = true
diff --git a/crates/material_theme/assets/themes/dark.toml b/crates/material_theme/assets/themes/dark.toml
deleted file mode 100644
index 18a369f..0000000
--- a/crates/material_theme/assets/themes/dark.toml
+++ /dev/null
@@ -1,49 +0,0 @@
-name = "Dark"
-
-shadow = "#000000"
-scrim = "#4d000000"
-
-[primary]
-color = "#9bd4a1"
-on_primary = "#003916"
-primary_container = "#1b5129"
-on_primary_container = "#b6f1bb"
-
-[secondary]
-color = "#b8ccb6"
-on_secondary = "#233425"
-secondary_container = "#394b3a"
-on_secondary_container = "#d3e8d1"
-
-[tertiary]
-color = "#a1ced7"
-on_tertiary = "#00363e"
-tertiary_container = "#1f4d55"
-on_tertiary_container = "#bdeaf4"
-
-[error]
-color = "#ffb4ab"
-on_error = "#690005"
-error_container = "#93000a"
-on_error_container = "#ffdad6"
-
-[surface]
-color = "#101510"
-on_surface = "#e0e4dc"
-on_surface_variant = "#c1c9be"
-
-[surface.surface_container]
-lowest = "#0b0f0b"
-low = "#181d18"
-base = "#1c211c"
-high = "#262b26"
-highest = "#313631"
-
-[inverse]
-inverse_surface = "#e0e4dc"
-inverse_on_surface = "#2d322c"
-inverse_primary = "#34693f"
-
-[outline]
-color = "#8b9389"
-variant = "#414941"
diff --git a/crates/material_theme/assets/themes/light.toml b/crates/material_theme/assets/themes/light.toml
deleted file mode 100644
index a7115c4..0000000
--- a/crates/material_theme/assets/themes/light.toml
+++ /dev/null
@@ -1,49 +0,0 @@
-name = "Light"
-
-shadow = "#000000"
-scrim = "#4d000000"
-
-[primary]
-color = "#34693f"
-on_primary = "#ffffff"
-primary_container = "#b6f1bb"
-on_primary_container = "#1b5129"
-
-[secondary]
-color = "#516351"
-on_secondary = "#ffffff"
-secondary_container = "#d3e8d1"
-on_secondary_container = "#394b3a"
-
-[tertiary]
-color = "#39656d"
-on_tertiary = "#ffffff"
-tertiary_container = "#bdeaf4"
-on_tertiary_container = "#1f4d55"
-
-[error]
-color = "#ba1a1a"
-on_error = "#ffffff"
-error_container = "#ffdad6"
-on_error_container = "#93000a"
-
-[surface]
-color = "#f7fbf2"
-on_surface = "#181d18"
-on_surface_variant = "#414941"
-
-[surface.surface_container]
-lowest = "#ffffff"
-low = "#f1f5ed"
-base = "#ebefe7"
-high = "#e5e9e1"
-highest = "#e0e4dc"
-
-[inverse]
-inverse_surface = "#2d322c"
-inverse_on_surface = "#eef2ea"
-inverse_primary = "#9bd4a1"
-
-[outline]
-color = "#727970"
-variant = "#c1c9be"
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<Theme> =
+ LazyLock::new(|| Theme::new("Dark", ColorScheme::DARK));
+pub static LIGHT: LazyLock<Theme> =
+ 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<Theme> = LazyLock::new(|| {
- toml::from_str(DARK_THEME_CONTENT).expect("parse dark theme")
-});
-
-pub static LIGHT: LazyLock<Theme> = 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<Color, D::Error>
where
@@ -256,4 +375,11 @@ mod color_serde {
.map(|hex| parse_argb(&hex))?
.unwrap_or(Color::TRANSPARENT))
}
+
+ pub fn serialize<S>(color: &Color, serializer: S) -> Result<S::Ok, S::Error>
+ 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<Color> {
})
}
+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;