diff options
| author | pml68 <contact@pml68.dev> | 2024-12-31 03:01:43 +0100 |
|---|---|---|
| committer | pml68 <contact@pml68.dev> | 2024-12-31 03:01:43 +0100 |
| commit | 4b6de2a4f8e793baf2caf7daedb9e401b24242a7 (patch) | |
| tree | f919a33de7737b0545158f28a715c35b0da490f8 /iced_builder | |
| parent | refactor: unsaved_changes_dialog emits bool instead of MessageDialogResult (diff) | |
| download | iced-builder-4b6de2a4f8e793baf2caf7daedb9e401b24242a7.tar.gz | |
feat: optionally define Extended Palette in custom theme
Diffstat (limited to '')
| -rw-r--r-- | iced_builder/assets/themes/Rose Pine.toml | 28 | ||||
| -rw-r--r-- | iced_builder/src/config.rs | 16 | ||||
| -rw-r--r-- | iced_builder/src/main.rs | 5 | ||||
| -rw-r--r-- | iced_builder/src/theme.rs | 162 | ||||
| -rwxr-xr-x | iced_builder/src/types/rendered_element.rs | 2 |
5 files changed, 196 insertions, 17 deletions
diff --git a/iced_builder/assets/themes/Rose Pine.toml b/iced_builder/assets/themes/Rose Pine.toml index a4eeeeb..df7342b 100644 --- a/iced_builder/assets/themes/Rose Pine.toml +++ b/iced_builder/assets/themes/Rose Pine.toml @@ -1,5 +1,33 @@ +is_dark = true + +[palette] background = "#26233a" text = "#e0def4" primary = "#9ccfd8" success = "#f6c177" danger = "#eb6f92" + +[background] +base = { color = "#191724", text = "#e0def4" } +weak = { color = "#1f1d2e", text = "#e0def4" } +strong = { color = "#26233a", text = "#f4ebd3" } + +[primary] +base = { color = "#eb6f92", text = "#000000" } +weak = { color = "#f6c177", text = "#000000" } +strong = { color = "#ebbcba", text = "#000000" } + +[secondary] +base = { color = "#31748f", text = "#ffffff" } +weak = { color = "#9ccfd8", text = "#000000" } +strong = { color = "#c4a7e7", text = "#000000" } + +[success] +base = { color = "#9ccfd8", text = "#000000" } +weak = { color = "#6e6a86", text = "#ffffff" } +strong = { color = "#908caa", text = "#000000" } + +[danger] +base = { color = "#eb6f92", text = "#ffffff" } +weak = { color = "#f6c177", text = "#ffffff" } +strong = { color = "#524f67", text = "#ffffff" } 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<PathBuf>, } @@ -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<PathBuf>, } @@ -73,17 +72,16 @@ impl Config { }) } - pub async fn load_theme(theme_name: String) -> Result<Theme> { + pub async fn load_theme(theme_name: String) -> Result<Appearance> { 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<bool>, + #[serde(flatten)] + extended: Option<ExtendedThemePalette>, +} + +#[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<ThemePalette> for iced::theme::Palette { } } +impl From<Theme> 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<ThemeBackground>, + primary: Option<ThemePrimary>, + secondary: Option<ThemeSecondary>, + success: Option<ThemeSuccess>, + danger: Option<ThemeDanger>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeBackground { + base: Option<ThemePair>, + weak: Option<ThemePair>, + strong: Option<ThemePair>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemePrimary { + base: Option<ThemePair>, + weak: Option<ThemePair>, + strong: Option<ThemePair>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeSecondary { + base: Option<ThemePair>, + weak: Option<ThemePair>, + strong: Option<ThemePair>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeSuccess { + base: Option<ThemePair>, + weak: Option<ThemePair>, + strong: Option<ThemePair>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemeDanger { + base: Option<ThemePair>, + weak: Option<ThemePair>, + strong: Option<ThemePair>, +} + +#[derive(Debug, Default, serde::Deserialize)] +struct ThemePair { + #[serde(with = "color_serde")] + color: Color, + #[serde(with = "color_serde")] + text: Color, +} + +impl From<ThemePair> 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<Vec<RenderedElement>>, name: ElementName, |
