From 4b6de2a4f8e793baf2caf7daedb9e401b24242a7 Mon Sep 17 00:00:00 2001 From: pml68 Date: Tue, 31 Dec 2024 03:01:43 +0100 Subject: feat: optionally define Extended Palette in custom theme --- iced_builder/src/config.rs | 16 ++- iced_builder/src/main.rs | 5 +- iced_builder/src/theme.rs | 162 ++++++++++++++++++++++++++++- iced_builder/src/types/rendered_element.rs | 2 +- 4 files changed, 168 insertions(+), 17 deletions(-) (limited to 'iced_builder/src') diff --git a/iced_builder/src/config.rs b/iced_builder/src/config.rs index 75aee1d..631b35a 100644 --- a/iced_builder/src/config.rs +++ b/iced_builder/src/config.rs @@ -4,12 +4,12 @@ use serde::Deserialize; use tokio_stream::wrappers::ReadDirStream; use tokio_stream::StreamExt; -use crate::theme::{theme_from_str, theme_index, Theme, ThemePalette}; +use crate::theme::{theme_from_str, theme_index, Appearance, Theme}; use crate::{environment, Error, Result}; #[derive(Debug, Default)] pub struct Config { - pub theme: Theme, + pub theme: Appearance, pub last_project: Option, } @@ -25,7 +25,6 @@ impl Config { std::fs::create_dir_all(dir.as_path()) .expect("expected permissions to create config folder"); } - println!("{}", dir.to_string_lossy()); dir } @@ -36,7 +35,6 @@ impl Config { std::fs::create_dir_all(dir.as_path()) .expect("expected permissions to create themes folder"); } - println!("{}", dir.to_string_lossy()); dir } @@ -49,6 +47,7 @@ impl Config { #[derive(Deserialize)] pub struct Configuration { + #[serde(default)] pub theme: String, pub last_project: Option, } @@ -73,17 +72,16 @@ impl Config { }) } - pub async fn load_theme(theme_name: String) -> Result { + pub async fn load_theme(theme_name: String) -> Result { use tokio::fs; let read_entry = |entry: fs::DirEntry| async move { let content = fs::read_to_string(entry.path()).await.ok()?; - let palette: ThemePalette = - toml::from_str(content.as_ref()).ok()?; + let theme: Theme = toml::from_str(content.as_ref()).ok()?; let name = entry.path().file_stem()?.to_string_lossy().to_string(); - Some(iced::Theme::custom(name, palette.into())) + Some(theme.into_iced_theme(name)) }; let mut all = iced::Theme::ALL.to_owned(); @@ -115,7 +113,7 @@ impl Config { } } - Ok(Theme { + Ok(Appearance { selected, all: all.into(), }) diff --git a/iced_builder/src/main.rs b/iced_builder/src/main.rs index 86e478d..8f3c3fb 100644 --- a/iced_builder/src/main.rs +++ b/iced_builder/src/main.rs @@ -66,10 +66,7 @@ impl App { ); let config = match config_load { - Ok(config) => { - println!("{config:?}"); - config - } + Ok(config) => config, Err(_) => Config::default(), }; diff --git a/iced_builder/src/theme.rs b/iced_builder/src/theme.rs index 21ec6e3..e41474c 100644 --- a/iced_builder/src/theme.rs +++ b/iced_builder/src/theme.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use iced::theme::palette::Extended; use iced::Color; use crate::config::Config; @@ -56,12 +57,12 @@ pub fn theme_from_str( } #[derive(Debug)] -pub struct Theme { +pub struct Appearance { pub selected: iced::Theme, pub all: Arc<[iced::Theme]>, } -impl Default for Theme { +impl Default for Appearance { fn default() -> Self { Self { selected: iced::Theme::default(), @@ -70,7 +71,15 @@ impl Default for Theme { } } -#[derive(Debug, serde::Deserialize)] +#[derive(Debug, Default, serde::Deserialize)] +pub struct Theme { + palette: ThemePalette, + is_dark: Option, + #[serde(flatten)] + extended: Option, +} + +#[derive(Debug, Clone, serde::Deserialize)] pub struct ThemePalette { #[serde(with = "color_serde")] background: Color, @@ -84,6 +93,14 @@ pub struct ThemePalette { danger: Color, } +impl Theme { + pub fn into_iced_theme(self, name: String) -> iced::Theme { + iced::Theme::custom_with_fn(name, self.palette.clone().into(), |_| { + self.into() + }) + } +} + impl Default for ThemePalette { fn default() -> Self { let palette = iced::Theme::default().palette(); @@ -109,6 +126,145 @@ impl From for iced::theme::Palette { } } +impl From for Extended { + fn from(theme: Theme) -> Self { + let mut extended = Extended::generate(theme.palette.into()); + + if let Some(is_dark) = theme.is_dark { + extended.is_dark = is_dark; + } + + if let Some(extended_palette) = theme.extended { + if let Some(background) = extended_palette.background { + if let Some(base) = background.base { + extended.background.base = base.into(); + } + if let Some(weak) = background.weak { + extended.background.weak = weak.into(); + } + if let Some(strong) = background.strong { + extended.background.strong = strong.into(); + } + } + + // Handle primary + if let Some(primary) = extended_palette.primary { + if let Some(base) = primary.base { + extended.primary.base = base.into(); + } + if let Some(weak) = primary.weak { + extended.primary.weak = weak.into(); + } + if let Some(strong) = primary.strong { + extended.primary.strong = strong.into(); + } + } + + // Handle secondary + if let Some(secondary) = extended_palette.secondary { + if let Some(base) = secondary.base { + extended.secondary.base = base.into(); + } + if let Some(weak) = secondary.weak { + extended.secondary.weak = weak.into(); + } + if let Some(strong) = secondary.strong { + extended.secondary.strong = strong.into(); + } + } + + // Handle success + if let Some(success) = extended_palette.success { + if let Some(base) = success.base { + extended.success.base = base.into(); + } + if let Some(weak) = success.weak { + extended.success.weak = weak.into(); + } + if let Some(strong) = success.strong { + extended.success.strong = strong.into(); + } + } + + // Handle danger + if let Some(danger) = extended_palette.danger { + if let Some(base) = danger.base { + extended.danger.base = base.into(); + } + if let Some(weak) = danger.weak { + extended.danger.weak = weak.into(); + } + if let Some(strong) = danger.strong { + extended.danger.strong = strong.into(); + } + } + } + + extended + } +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ExtendedThemePalette { + background: Option, + primary: Option, + secondary: Option, + success: Option, + danger: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeBackground { + base: Option, + weak: Option, + strong: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemePrimary { + base: Option, + weak: Option, + strong: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeSecondary { + base: Option, + weak: Option, + strong: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeSuccess { + base: Option, + weak: Option, + strong: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeDanger { + base: Option, + weak: Option, + strong: Option, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemePair { + #[serde(with = "color_serde")] + color: Color, + #[serde(with = "color_serde")] + text: Color, +} + +impl From for iced::theme::palette::Pair { + fn from(pair: ThemePair) -> Self { + Self { + color: pair.color, + text: pair.text, + } + } +} + mod color_serde { use iced::Color; use serde::{Deserialize, Deserializer}; diff --git a/iced_builder/src/types/rendered_element.rs b/iced_builder/src/types/rendered_element.rs index 5270e5a..e837abe 100755 --- a/iced_builder/src/types/rendered_element.rs +++ b/iced_builder/src/types/rendered_element.rs @@ -11,7 +11,7 @@ use crate::Result; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RenderedElement { - #[serde(skip)] + #[serde(skip, default = "Uuid::new_v4")] id: Uuid, child_elements: Option>, name: ElementName, -- cgit v1.2.3