Use theme families to refine user themes (#19936)
This PR changes the way we load user themes into the ThemeRegistry. Rather than directly pass a theme family's themes to `insert_user_themes`, instead we use the new `refine_theme_family ` and `ThemeFamily::refine_theme`. This PR should have net zero change to themes today, but sets up enabling theme variables. We need to do it this way so each theme has access to it's family when it is refined. Release Notes: - N/A
This commit is contained in:
+109
-3
@@ -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)]
|
||||
|
||||
Reference in New Issue
Block a user