Define theme/ui text style settings in theme crate

This commit is contained in:
Max Brunsfeld
2023-05-17 14:44:59 -07:00
parent 5c729c0e56
commit 67a25126d4
86 changed files with 530 additions and 637 deletions
+15 -3
View File
@@ -1,19 +1,31 @@
mod theme_registry;
mod theme_settings;
pub mod ui;
use gpui::{
color::Color,
elements::{ContainerStyle, ImageStyle, LabelStyle, Shadow, TooltipStyle},
fonts::{HighlightStyle, TextStyle},
platform, Border, MouseState,
platform, AppContext, AssetSource, Border, MouseState,
};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::Value;
use std::{collections::HashMap, sync::Arc};
use ui::{ButtonStyle, CheckboxStyle, IconStyle, ModalStyle, SvgStyle};
pub mod ui;
pub use theme_registry::ThemeRegistry;
pub use theme_settings::ThemeSettings;
pub use theme_registry::*;
pub fn current(cx: &AppContext) -> Arc<Theme> {
settings::get_setting::<ThemeSettings>(None, cx)
.theme
.clone()
}
pub fn init(source: impl AssetSource, cx: &mut AppContext) {
cx.set_global(ThemeRegistry::new(source, cx.font_cache().clone()));
settings::register_setting::<ThemeSettings>(cx);
}
#[derive(Deserialize, Default)]
pub struct Theme {
+7 -5
View File
@@ -20,9 +20,6 @@ pub struct ThemeRegistry {
next_theme_id: AtomicUsize,
}
#[cfg(any(test, feature = "test-support"))]
pub const EMPTY_THEME_NAME: &'static str = "empty-theme";
impl ThemeRegistry {
pub fn new(source: impl AssetSource, font_cache: Arc<FontCache>) -> Arc<Self> {
let this = Arc::new(Self {
@@ -35,8 +32,13 @@ impl ThemeRegistry {
#[cfg(any(test, feature = "test-support"))]
this.themes.lock().insert(
EMPTY_THEME_NAME.to_string(),
gpui::fonts::with_font_cache(this.font_cache.clone(), || Arc::new(Theme::default())),
settings::EMPTY_THEME_NAME.to_string(),
gpui::fonts::with_font_cache(this.font_cache.clone(), || {
let mut theme = Theme::default();
theme.meta.id = this.next_theme_id.fetch_add(1, SeqCst);
theme.meta.name = settings::EMPTY_THEME_NAME.into();
Arc::new(theme)
}),
);
this
+136
View File
@@ -0,0 +1,136 @@
use crate::{Theme, ThemeRegistry};
use anyhow::Result;
use gpui::{font_cache::FamilyId, fonts, AppContext};
use schemars::{
gen::SchemaGenerator,
schema::{InstanceType, Schema, SchemaObject},
JsonSchema,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use settings::SettingsJsonSchemaParams;
use std::sync::Arc;
use util::ResultExt as _;
#[derive(Clone)]
pub struct ThemeSettings {
pub buffer_font_family_name: String,
pub buffer_font_features: fonts::Features,
pub buffer_font_family: FamilyId,
pub buffer_font_size: f32,
pub theme: Arc<Theme>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
pub struct ThemeSettingsContent {
#[serde(default)]
pub buffer_font_family: Option<String>,
#[serde(default)]
pub buffer_font_size: Option<f32>,
#[serde(default)]
pub buffer_font_features: Option<fonts::Features>,
#[serde(default)]
pub theme: Option<String>,
}
impl settings::Setting for ThemeSettings {
const KEY: Option<&'static str> = None;
type FileContent = ThemeSettingsContent;
fn load(
defaults: &Self::FileContent,
user_values: &[&Self::FileContent],
cx: &AppContext,
) -> Result<Self> {
let buffer_font_features = defaults.buffer_font_features.clone().unwrap();
let themes = cx.global::<Arc<ThemeRegistry>>();
let mut this = Self {
buffer_font_family: cx
.font_cache()
.load_family(
&[defaults.buffer_font_family.as_ref().unwrap()],
&buffer_font_features,
)
.unwrap(),
buffer_font_family_name: defaults.buffer_font_family.clone().unwrap(),
buffer_font_features,
buffer_font_size: defaults.buffer_font_size.unwrap(),
theme: themes.get(defaults.theme.as_ref().unwrap()).unwrap(),
};
for value in user_values.into_iter().copied().cloned() {
let font_cache = cx.font_cache();
let mut family_changed = false;
if let Some(value) = value.buffer_font_family {
this.buffer_font_family_name = value;
family_changed = true;
}
if let Some(value) = value.buffer_font_features {
this.buffer_font_features = value;
family_changed = true;
}
if family_changed {
if let Some(id) = font_cache
.load_family(&[&this.buffer_font_family_name], &this.buffer_font_features)
.log_err()
{
this.buffer_font_family = id;
}
}
if let Some(value) = &value.theme {
if let Some(theme) = themes.get(value).log_err() {
this.theme = theme;
}
}
merge(&mut this.buffer_font_size, value.buffer_font_size);
}
Ok(this)
}
fn json_schema(
generator: &mut SchemaGenerator,
params: &SettingsJsonSchemaParams,
cx: &AppContext,
) -> schemars::schema::RootSchema {
let mut root_schema = generator.root_schema_for::<ThemeSettingsContent>();
let theme_names = cx
.global::<Arc<ThemeRegistry>>()
.list(params.staff_mode)
.map(|theme| Value::String(theme.name.clone()))
.collect();
let theme_name_schema = SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(theme_names),
..Default::default()
};
root_schema
.definitions
.extend([("ThemeName".into(), theme_name_schema.into())]);
root_schema
.schema
.object
.as_mut()
.unwrap()
.properties
.extend([(
"theme".to_owned(),
Schema::new_ref("#/definitions/ThemeName".into()),
)]);
root_schema
}
}
fn merge<T: Copy>(target: &mut T, value: Option<T>) {
if let Some(value) = value {
*target = value;
}
}