@@ -6,16 +6,11 @@ use collections::HashMap;
use derive_more::{Deref, DerefMut};
use fs::Fs;
use futures::StreamExt;
-use gpui::{AppContext, AssetSource, Global, HighlightStyle, SharedString};
+use gpui::{AppContext, AssetSource, Global, SharedString};
use parking_lot::RwLock;
-use refineable::Refineable;
use util::ResultExt;
-use crate::{
- try_parse_color, AccentColors, Appearance, AppearanceContent, PlayerColors, StatusColors,
- SyntaxTheme, SystemColors, Theme, ThemeColors, ThemeContent, ThemeFamily, ThemeFamilyContent,
- ThemeStyles,
-};
+use crate::{refine_theme_family, Appearance, Theme, ThemeFamily, ThemeFamilyContent};
/// The metadata for a theme.
#[derive(Debug, Clone)]
@@ -97,87 +92,10 @@ impl ThemeRegistry {
#[allow(unused)]
fn insert_user_theme_families(&self, families: impl IntoIterator<Item = ThemeFamilyContent>) {
for family in families.into_iter() {
- self.insert_user_themes(family.themes);
- }
- }
-
- /// Inserts user themes into the registry.
- pub fn insert_user_themes(&self, themes: impl IntoIterator<Item = ThemeContent>) {
- self.insert_themes(themes.into_iter().map(|user_theme| {
- let mut theme_colors = match user_theme.appearance {
- AppearanceContent::Light => ThemeColors::light(),
- AppearanceContent::Dark => ThemeColors::dark(),
- };
- theme_colors.refine(&user_theme.style.theme_colors_refinement());
-
- let mut status_colors = match user_theme.appearance {
- AppearanceContent::Light => StatusColors::light(),
- AppearanceContent::Dark => StatusColors::dark(),
- };
- status_colors.refine(&user_theme.style.status_colors_refinement());
-
- let mut player_colors = match user_theme.appearance {
- AppearanceContent::Light => PlayerColors::light(),
- AppearanceContent::Dark => PlayerColors::dark(),
- };
- player_colors.merge(&user_theme.style.players);
-
- let mut accent_colors = match user_theme.appearance {
- AppearanceContent::Light => AccentColors::light(),
- AppearanceContent::Dark => AccentColors::dark(),
- };
- accent_colors.merge(&user_theme.style.accents);
+ let refined_family = refine_theme_family(family);
- let syntax_highlights = user_theme
- .style
- .syntax
- .iter()
- .map(|(syntax_token, highlight)| {
- (
- syntax_token.clone(),
- HighlightStyle {
- color: highlight
- .color
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
- background_color: highlight
- .background_color
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
- font_style: highlight.font_style.map(Into::into),
- font_weight: highlight.font_weight.map(Into::into),
- ..Default::default()
- },
- )
- })
- .collect::<Vec<_>>();
- let syntax_theme =
- SyntaxTheme::merge(Arc::new(SyntaxTheme::default()), syntax_highlights);
-
- let window_background_appearance = user_theme
- .style
- .window_background_appearance
- .map(Into::into)
- .unwrap_or_default();
-
- Theme {
- id: uuid::Uuid::new_v4().to_string(),
- name: user_theme.name.into(),
- appearance: match user_theme.appearance {
- AppearanceContent::Light => Appearance::Light,
- AppearanceContent::Dark => Appearance::Dark,
- },
- styles: ThemeStyles {
- system: SystemColors::default(),
- window_background_appearance,
- accents: accent_colors,
- colors: theme_colors,
- status: status_colors,
- player: player_colors,
- syntax: syntax_theme,
- },
- }
- }));
+ self.insert_themes(refined_family.themes);
+ }
}
/// Removes the themes with the given names from the registry.
@@ -29,10 +29,11 @@ pub use settings::*;
pub use styles::*;
use gpui::{
- px, AppContext, AssetSource, Hsla, Pixels, SharedString, WindowAppearance,
- WindowBackgroundAppearance,
+ px, AppContext, AssetSource, HighlightStyle, Hsla, Pixels, Refineable, SharedString,
+ WindowAppearance, WindowBackgroundAppearance,
};
use serde::Deserialize;
+use uuid::Uuid;
/// Defines window border radius for platforms that use client side decorations.
pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0);
@@ -137,7 +138,112 @@ pub struct ThemeFamily {
pub scales: ColorScales,
}
-impl ThemeFamily {}
+impl ThemeFamily {
+ // This is on ThemeFamily because we will have variables here we will need
+ // in the future to resolve @references.
+ /// Refines ThemeContent into a theme, merging it's contents with the base theme.
+ pub fn refine_theme(&self, theme: &ThemeContent) -> Theme {
+ let appearance = match theme.appearance {
+ AppearanceContent::Light => Appearance::Light,
+ AppearanceContent::Dark => Appearance::Dark,
+ };
+
+ let mut refined_theme_colors = match theme.appearance {
+ AppearanceContent::Light => ThemeColors::light(),
+ AppearanceContent::Dark => ThemeColors::dark(),
+ };
+ refined_theme_colors.refine(&theme.style.theme_colors_refinement());
+
+ let mut refined_status_colors = match theme.appearance {
+ AppearanceContent::Light => StatusColors::light(),
+ AppearanceContent::Dark => StatusColors::dark(),
+ };
+ refined_status_colors.refine(&theme.style.status_colors_refinement());
+
+ let mut refined_player_colors = match theme.appearance {
+ AppearanceContent::Light => PlayerColors::light(),
+ AppearanceContent::Dark => PlayerColors::dark(),
+ };
+ refined_player_colors.merge(&theme.style.players);
+
+ let mut refined_accent_colors = match theme.appearance {
+ AppearanceContent::Light => AccentColors::light(),
+ AppearanceContent::Dark => AccentColors::dark(),
+ };
+ refined_accent_colors.merge(&theme.style.accents);
+
+ let syntax_highlights = theme
+ .style
+ .syntax
+ .iter()
+ .map(|(syntax_token, highlight)| {
+ (
+ syntax_token.clone(),
+ HighlightStyle {
+ color: highlight
+ .color
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok()),
+ background_color: highlight
+ .background_color
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok()),
+ font_style: highlight.font_style.map(Into::into),
+ font_weight: highlight.font_weight.map(Into::into),
+ ..Default::default()
+ },
+ )
+ })
+ .collect::<Vec<_>>();
+ let syntax_theme = SyntaxTheme::merge(Arc::new(SyntaxTheme::default()), syntax_highlights);
+
+ let window_background_appearance = theme
+ .style
+ .window_background_appearance
+ .map(Into::into)
+ .unwrap_or_default();
+
+ Theme {
+ id: uuid::Uuid::new_v4().to_string(),
+ name: theme.name.clone().into(),
+ appearance,
+ styles: ThemeStyles {
+ system: SystemColors::default(),
+ window_background_appearance,
+ accents: refined_accent_colors,
+ colors: refined_theme_colors,
+ status: refined_status_colors,
+ player: refined_player_colors,
+ syntax: syntax_theme,
+ },
+ }
+ }
+}
+
+/// Refines a [ThemeFamilyContent] and it's [ThemeContent]s into a [ThemeFamily].
+pub fn refine_theme_family(theme_family_content: ThemeFamilyContent) -> ThemeFamily {
+ let id = Uuid::new_v4().to_string();
+ let name = theme_family_content.name.clone();
+ let author = theme_family_content.author.clone();
+
+ let mut theme_family = ThemeFamily {
+ id: id.clone(),
+ name: name.clone().into(),
+ author: author.clone().into(),
+ themes: vec![],
+ scales: default_color_scales(),
+ };
+
+ let refined_themes = theme_family_content
+ .themes
+ .iter()
+ .map(|theme_content| theme_family.refine_theme(theme_content))
+ .collect();
+
+ theme_family.themes = refined_themes;
+
+ theme_family
+}
/// A theme is the primary mechanism for defining the appearance of the UI.
#[derive(Clone, PartialEq)]