Reland "Remove cx from ThemeSettings" (#39720)
- **Reapply "Remove cx from ThemeSettings (#38836)" (#39691)** - **Fix theme loading races** Closes #ISSUE Release Notes: - N/A
This commit is contained in:
@@ -3,9 +3,9 @@ use std::sync::Arc;
|
||||
use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla, WindowBackgroundAppearance, hsla};
|
||||
|
||||
use crate::{
|
||||
AccentColors, Appearance, PlayerColors, StatusColors, StatusColorsRefinement, SyntaxTheme,
|
||||
SystemColors, Theme, ThemeColors, ThemeColorsRefinement, ThemeFamily, ThemeStyles,
|
||||
default_color_scales,
|
||||
AccentColors, Appearance, DEFAULT_DARK_THEME, PlayerColors, StatusColors,
|
||||
StatusColorsRefinement, SyntaxTheme, SystemColors, Theme, ThemeColors, ThemeColorsRefinement,
|
||||
ThemeFamily, ThemeStyles, default_color_scales,
|
||||
};
|
||||
|
||||
/// The default theme family for Zed.
|
||||
@@ -92,7 +92,7 @@ pub(crate) fn zed_default_dark() -> Theme {
|
||||
let player = PlayerColors::dark();
|
||||
Theme {
|
||||
id: "one_dark".to_string(),
|
||||
name: "One Dark".into(),
|
||||
name: DEFAULT_DARK_THEME.into(),
|
||||
appearance: Appearance::Dark,
|
||||
styles: ThemeStyles {
|
||||
window_background_appearance: WindowBackgroundAppearance::Opaque,
|
||||
|
||||
+41
-169
@@ -1,8 +1,6 @@
|
||||
use crate::fallback_themes::zed_default_dark;
|
||||
use crate::{
|
||||
Appearance, DEFAULT_ICON_THEME_NAME, IconTheme, IconThemeNotFoundError, SyntaxTheme, Theme,
|
||||
ThemeNotFoundError, ThemeRegistry, status_colors_refinement, syntax_overrides,
|
||||
theme_colors_refinement,
|
||||
Appearance, DEFAULT_ICON_THEME_NAME, SyntaxTheme, Theme, status_colors_refinement,
|
||||
syntax_overrides, theme_colors_refinement,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
@@ -16,7 +14,6 @@ use serde::{Deserialize, Serialize};
|
||||
pub use settings::{FontFamilyName, IconThemeName, ThemeMode, ThemeName};
|
||||
use settings::{Settings, SettingsContent};
|
||||
use std::sync::Arc;
|
||||
use util::ResultExt as _;
|
||||
|
||||
const MIN_FONT_SIZE: Pixels = px(6.0);
|
||||
const MAX_FONT_SIZE: Pixels = px(100.0);
|
||||
@@ -125,9 +122,7 @@ pub struct ThemeSettings {
|
||||
/// The terminal font family can be overridden using it's own setting.
|
||||
pub buffer_line_height: BufferLineHeight,
|
||||
/// The current theme selection.
|
||||
pub theme_selection: Option<ThemeSelection>,
|
||||
/// The active theme.
|
||||
pub active_theme: Arc<Theme>,
|
||||
pub theme: ThemeSelection,
|
||||
/// Manual overrides for the active theme.
|
||||
///
|
||||
/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078)
|
||||
@@ -135,9 +130,7 @@ pub struct ThemeSettings {
|
||||
/// Manual overrides per theme
|
||||
pub theme_overrides: HashMap<String, settings::ThemeStyleContent>,
|
||||
/// The current icon theme selection.
|
||||
pub icon_theme_selection: Option<IconThemeSelection>,
|
||||
/// The active icon theme.
|
||||
pub active_icon_theme: Arc<IconTheme>,
|
||||
pub icon_theme: IconThemeSelection,
|
||||
/// The density of the UI.
|
||||
/// Note: This setting is still experimental. See [this tracking issue](
|
||||
pub ui_density: UiDensity,
|
||||
@@ -145,73 +138,14 @@ pub struct ThemeSettings {
|
||||
pub unnecessary_code_fade: f32,
|
||||
}
|
||||
|
||||
impl ThemeSettings {
|
||||
const DEFAULT_LIGHT_THEME: &'static str = "One Light";
|
||||
const DEFAULT_DARK_THEME: &'static str = "One Dark";
|
||||
pub(crate) const DEFAULT_LIGHT_THEME: &'static str = "One Light";
|
||||
pub(crate) const DEFAULT_DARK_THEME: &'static str = "One Dark";
|
||||
|
||||
/// Returns the name of the default theme for the given [`Appearance`].
|
||||
pub fn default_theme(appearance: Appearance) -> &'static str {
|
||||
match appearance {
|
||||
Appearance::Light => Self::DEFAULT_LIGHT_THEME,
|
||||
Appearance::Dark => Self::DEFAULT_DARK_THEME,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reloads the current theme.
|
||||
///
|
||||
/// Reads the [`ThemeSettings`] to know which theme should be loaded,
|
||||
/// taking into account the current [`SystemAppearance`].
|
||||
pub fn reload_current_theme(cx: &mut App) {
|
||||
let mut theme_settings = ThemeSettings::get_global(cx).clone();
|
||||
let system_appearance = SystemAppearance::global(cx);
|
||||
|
||||
if let Some(theme_selection) = theme_settings.theme_selection.clone() {
|
||||
let mut theme_name = theme_selection.theme(*system_appearance);
|
||||
|
||||
// If the selected theme doesn't exist, fall back to a default theme
|
||||
// based on the system appearance.
|
||||
let theme_registry = ThemeRegistry::global(cx);
|
||||
if let Err(err @ ThemeNotFoundError(_)) = theme_registry.get(theme_name) {
|
||||
if theme_registry.extensions_loaded() {
|
||||
log::error!("{err}");
|
||||
}
|
||||
|
||||
theme_name = Self::default_theme(*system_appearance);
|
||||
};
|
||||
|
||||
if let Some(_theme) = theme_settings.switch_theme(theme_name, cx) {
|
||||
ThemeSettings::override_global(theme_settings, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reloads the current icon theme.
|
||||
///
|
||||
/// Reads the [`ThemeSettings`] to know which icon theme should be loaded,
|
||||
/// taking into account the current [`SystemAppearance`].
|
||||
pub fn reload_current_icon_theme(cx: &mut App) {
|
||||
let mut theme_settings = ThemeSettings::get_global(cx).clone();
|
||||
let system_appearance = SystemAppearance::global(cx);
|
||||
|
||||
if let Some(icon_theme_selection) = theme_settings.icon_theme_selection.clone() {
|
||||
let mut icon_theme_name = icon_theme_selection.icon_theme(*system_appearance);
|
||||
|
||||
// If the selected icon theme doesn't exist, fall back to the default theme.
|
||||
let theme_registry = ThemeRegistry::global(cx);
|
||||
if let Err(err @ IconThemeNotFoundError(_)) =
|
||||
theme_registry.get_icon_theme(icon_theme_name)
|
||||
{
|
||||
if theme_registry.extensions_loaded() {
|
||||
log::error!("{err}");
|
||||
}
|
||||
|
||||
icon_theme_name = DEFAULT_ICON_THEME_NAME;
|
||||
};
|
||||
|
||||
if let Some(_theme) = theme_settings.switch_icon_theme(icon_theme_name, cx) {
|
||||
ThemeSettings::override_global(theme_settings, cx);
|
||||
}
|
||||
}
|
||||
/// Returns the name of the default theme for the given [`Appearance`].
|
||||
pub fn default_theme(appearance: Appearance) -> &'static str {
|
||||
match appearance {
|
||||
Appearance::Light => DEFAULT_LIGHT_THEME,
|
||||
Appearance::Dark => DEFAULT_DARK_THEME,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,13 +171,6 @@ impl SystemAppearance {
|
||||
GlobalSystemAppearance(SystemAppearance(cx.window_appearance().into()));
|
||||
}
|
||||
|
||||
/// Returns the global [`SystemAppearance`].
|
||||
///
|
||||
/// Inserts a default [`SystemAppearance`] if one does not yet exist.
|
||||
pub(crate) fn default_global(cx: &mut App) -> Self {
|
||||
cx.default_global::<GlobalSystemAppearance>().0
|
||||
}
|
||||
|
||||
/// Returns the global [`SystemAppearance`].
|
||||
pub fn global(cx: &App) -> Self {
|
||||
cx.global::<GlobalSystemAppearance>().0
|
||||
@@ -302,15 +229,15 @@ impl From<settings::ThemeSelection> for ThemeSelection {
|
||||
|
||||
impl ThemeSelection {
|
||||
/// Returns the theme name for the selected [ThemeMode].
|
||||
pub fn theme(&self, system_appearance: Appearance) -> &str {
|
||||
pub fn name(&self, system_appearance: Appearance) -> ThemeName {
|
||||
match self {
|
||||
Self::Static(theme) => &theme.0,
|
||||
Self::Static(theme) => theme.clone(),
|
||||
Self::Dynamic { mode, light, dark } => match mode {
|
||||
ThemeMode::Light => &light.0,
|
||||
ThemeMode::Dark => &dark.0,
|
||||
ThemeMode::Light => light.clone(),
|
||||
ThemeMode::Dark => dark.clone(),
|
||||
ThemeMode::System => match system_appearance {
|
||||
Appearance::Light => &light.0,
|
||||
Appearance::Dark => &dark.0,
|
||||
Appearance::Light => light.clone(),
|
||||
Appearance::Dark => dark.clone(),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -354,15 +281,15 @@ impl From<settings::IconThemeSelection> for IconThemeSelection {
|
||||
|
||||
impl IconThemeSelection {
|
||||
/// Returns the icon theme name based on the given [`Appearance`].
|
||||
pub fn icon_theme(&self, system_appearance: Appearance) -> &str {
|
||||
pub fn name(&self, system_appearance: Appearance) -> IconThemeName {
|
||||
match self {
|
||||
Self::Static(theme) => &theme.0,
|
||||
Self::Static(theme) => theme.clone(),
|
||||
Self::Dynamic { mode, light, dark } => match mode {
|
||||
ThemeMode::Light => &light.0,
|
||||
ThemeMode::Dark => &dark.0,
|
||||
ThemeMode::Light => light.clone(),
|
||||
ThemeMode::Dark => dark.clone(),
|
||||
ThemeMode::System => match system_appearance {
|
||||
Appearance::Light => &light.0,
|
||||
Appearance::Dark => &dark.0,
|
||||
Appearance::Light => light.clone(),
|
||||
Appearance::Dark => dark.clone(),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -408,7 +335,7 @@ pub fn set_theme(
|
||||
/// Sets the icon theme for the given appearance to the icon theme with the specified name.
|
||||
pub fn set_icon_theme(
|
||||
current: &mut SettingsContent,
|
||||
icon_theme_name: String,
|
||||
icon_theme_name: IconThemeName,
|
||||
appearance: Appearance,
|
||||
) {
|
||||
if let Some(selection) = current.theme.icon_theme.as_mut() {
|
||||
@@ -424,11 +351,9 @@ pub fn set_icon_theme(
|
||||
},
|
||||
};
|
||||
|
||||
*icon_theme_to_update = IconThemeName(icon_theme_name.into());
|
||||
*icon_theme_to_update = icon_theme_name;
|
||||
} else {
|
||||
current.theme.icon_theme = Some(settings::IconThemeSelection::Static(IconThemeName(
|
||||
icon_theme_name.into(),
|
||||
)));
|
||||
current.theme.icon_theme = Some(settings::IconThemeSelection::Static(icon_theme_name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,8 +381,8 @@ pub fn set_mode(content: &mut SettingsContent, mode: ThemeMode) {
|
||||
} else {
|
||||
theme.theme = Some(settings::ThemeSelection::Dynamic {
|
||||
mode,
|
||||
light: ThemeName(ThemeSettings::DEFAULT_LIGHT_THEME.into()),
|
||||
dark: ThemeName(ThemeSettings::DEFAULT_DARK_THEME.into()),
|
||||
light: ThemeName(DEFAULT_LIGHT_THEME.into()),
|
||||
dark: ThemeName(DEFAULT_DARK_THEME.into()),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -596,44 +521,22 @@ impl ThemeSettings {
|
||||
f32::max(self.buffer_line_height.value(), MIN_LINE_HEIGHT)
|
||||
}
|
||||
|
||||
/// Switches to the theme with the given name, if it exists.
|
||||
///
|
||||
/// Returns a `Some` containing the new theme if it was successful.
|
||||
/// Returns `None` otherwise.
|
||||
pub fn switch_theme(&mut self, theme: &str, cx: &mut App) -> Option<Arc<Theme>> {
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
|
||||
let mut new_theme = None;
|
||||
|
||||
match themes.get(theme) {
|
||||
Ok(theme) => {
|
||||
self.active_theme = theme.clone();
|
||||
new_theme = Some(theme);
|
||||
}
|
||||
Err(err @ ThemeNotFoundError(_)) => {
|
||||
log::error!("{err}");
|
||||
}
|
||||
}
|
||||
|
||||
self.apply_theme_overrides();
|
||||
|
||||
new_theme
|
||||
}
|
||||
|
||||
/// Applies the theme overrides, if there are any, to the current theme.
|
||||
pub fn apply_theme_overrides(&mut self) {
|
||||
pub fn apply_theme_overrides(&self, mut arc_theme: Arc<Theme>) -> Arc<Theme> {
|
||||
// Apply the old overrides setting first, so that the new setting can override those.
|
||||
if let Some(experimental_theme_overrides) = &self.experimental_theme_overrides {
|
||||
let mut theme = (*self.active_theme).clone();
|
||||
let mut theme = (*arc_theme).clone();
|
||||
ThemeSettings::modify_theme(&mut theme, experimental_theme_overrides);
|
||||
self.active_theme = Arc::new(theme);
|
||||
arc_theme = Arc::new(theme);
|
||||
}
|
||||
|
||||
if let Some(theme_overrides) = self.theme_overrides.get(self.active_theme.name.as_ref()) {
|
||||
let mut theme = (*self.active_theme).clone();
|
||||
if let Some(theme_overrides) = self.theme_overrides.get(arc_theme.name.as_ref()) {
|
||||
let mut theme = (*arc_theme).clone();
|
||||
ThemeSettings::modify_theme(&mut theme, theme_overrides);
|
||||
self.active_theme = Arc::new(theme);
|
||||
arc_theme = Arc::new(theme);
|
||||
}
|
||||
|
||||
arc_theme
|
||||
}
|
||||
|
||||
fn modify_theme(base_theme: &mut Theme, theme_overrides: &settings::ThemeStyleContent) {
|
||||
@@ -654,24 +557,6 @@ impl ThemeSettings {
|
||||
syntax_overrides(&theme_overrides),
|
||||
);
|
||||
}
|
||||
|
||||
/// Switches to the icon theme with the given name, if it exists.
|
||||
///
|
||||
/// Returns a `Some` containing the new icon theme if it was successful.
|
||||
/// Returns `None` otherwise.
|
||||
pub fn switch_icon_theme(&mut self, icon_theme: &str, cx: &mut App) -> Option<Arc<IconTheme>> {
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
|
||||
let mut new_icon_theme = None;
|
||||
|
||||
if let Some(icon_theme) = themes.get_icon_theme(icon_theme).log_err() {
|
||||
self.active_icon_theme = icon_theme.clone();
|
||||
new_icon_theme = Some(icon_theme);
|
||||
cx.refresh_windows();
|
||||
}
|
||||
|
||||
new_icon_theme
|
||||
}
|
||||
}
|
||||
|
||||
/// Observe changes to the adjusted buffer font size.
|
||||
@@ -804,14 +689,11 @@ pub fn font_fallbacks_from_settings(
|
||||
}
|
||||
|
||||
impl settings::Settings for ThemeSettings {
|
||||
fn from_settings(content: &settings::SettingsContent, cx: &mut App) -> Self {
|
||||
fn from_settings(content: &settings::SettingsContent) -> Self {
|
||||
let content = &content.theme;
|
||||
// todo(settings_refactor). This should *not* require cx...
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
let system_appearance = SystemAppearance::default_global(cx);
|
||||
let theme_selection: ThemeSelection = content.theme.clone().unwrap().into();
|
||||
let icon_theme_selection: IconThemeSelection = content.icon_theme.clone().unwrap().into();
|
||||
let mut this = Self {
|
||||
Self {
|
||||
ui_font_size: clamp_font_size(content.ui_font_size.unwrap().into()),
|
||||
ui_font: Font {
|
||||
family: content.ui_font_family.as_ref().unwrap().0.clone().into(),
|
||||
@@ -837,23 +719,13 @@ impl settings::Settings for ThemeSettings {
|
||||
buffer_line_height: content.buffer_line_height.unwrap().into(),
|
||||
agent_ui_font_size: content.agent_ui_font_size.map(Into::into),
|
||||
agent_buffer_font_size: content.agent_buffer_font_size.map(Into::into),
|
||||
active_theme: themes
|
||||
.get(theme_selection.theme(*system_appearance))
|
||||
.or(themes.get(&zed_default_dark().name))
|
||||
.unwrap(),
|
||||
theme_selection: Some(theme_selection),
|
||||
theme: theme_selection,
|
||||
experimental_theme_overrides: content.experimental_theme_overrides.clone(),
|
||||
theme_overrides: content.theme_overrides.clone(),
|
||||
active_icon_theme: themes
|
||||
.get_icon_theme(icon_theme_selection.icon_theme(*system_appearance))
|
||||
.or_else(|_| themes.default_icon_theme())
|
||||
.unwrap(),
|
||||
icon_theme_selection: Some(icon_theme_selection),
|
||||
icon_theme: icon_theme_selection,
|
||||
ui_density: content.ui_density.unwrap_or_default().into(),
|
||||
unnecessary_code_fade: content.unnecessary_code_fade.unwrap().0.clamp(0.0, 0.9),
|
||||
};
|
||||
this.apply_theme_overrides();
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut SettingsContent) {
|
||||
|
||||
+123
-14
@@ -27,6 +27,8 @@ use ::settings::SettingsStore;
|
||||
use anyhow::Result;
|
||||
use fallback_themes::apply_status_color_defaults;
|
||||
use fs::Fs;
|
||||
use gpui::BorrowAppContext;
|
||||
use gpui::Global;
|
||||
use gpui::{
|
||||
App, AssetSource, HighlightStyle, Hsla, Pixels, Refineable, SharedString, WindowAppearance,
|
||||
WindowBackgroundAppearance, px,
|
||||
@@ -95,6 +97,7 @@ pub enum LoadThemes {
|
||||
|
||||
/// Initialize the theme system.
|
||||
pub fn init(themes_to_load: LoadThemes, cx: &mut App) {
|
||||
SystemAppearance::init(cx);
|
||||
let (assets, load_user_themes) = match themes_to_load {
|
||||
LoadThemes::JustBase => (Box::new(()) as Box<dyn AssetSource>, false),
|
||||
LoadThemes::All(assets) => (assets, true),
|
||||
@@ -108,40 +111,67 @@ pub fn init(themes_to_load: LoadThemes, cx: &mut App) {
|
||||
ThemeSettings::register(cx);
|
||||
FontFamilyCache::init_global(cx);
|
||||
|
||||
let mut prev_buffer_font_size_settings =
|
||||
ThemeSettings::get_global(cx).buffer_font_size_settings();
|
||||
let mut prev_ui_font_size_settings = ThemeSettings::get_global(cx).ui_font_size_settings();
|
||||
let mut prev_agent_ui_font_size_settings =
|
||||
ThemeSettings::get_global(cx).agent_ui_font_size_settings();
|
||||
let mut prev_agent_buffer_font_size_settings =
|
||||
ThemeSettings::get_global(cx).agent_buffer_font_size_settings();
|
||||
let theme = GlobalTheme::configured_theme(cx);
|
||||
let icon_theme = GlobalTheme::configured_icon_theme(cx);
|
||||
cx.set_global(GlobalTheme { theme, icon_theme });
|
||||
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
|
||||
let mut prev_buffer_font_size_settings = settings.buffer_font_size_settings();
|
||||
let mut prev_ui_font_size_settings = settings.ui_font_size_settings();
|
||||
let mut prev_agent_ui_font_size_settings = settings.agent_ui_font_size_settings();
|
||||
let mut prev_agent_buffer_font_size_settings = settings.agent_buffer_font_size_settings();
|
||||
let mut prev_theme_name = settings.theme.name(SystemAppearance::global(cx).0);
|
||||
let mut prev_icon_theme_name = settings.icon_theme.name(SystemAppearance::global(cx).0);
|
||||
let mut prev_theme_overrides = (
|
||||
settings.experimental_theme_overrides.clone(),
|
||||
settings.theme_overrides.clone(),
|
||||
);
|
||||
|
||||
cx.observe_global::<SettingsStore>(move |cx| {
|
||||
let buffer_font_size_settings = ThemeSettings::get_global(cx).buffer_font_size_settings();
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
|
||||
let buffer_font_size_settings = settings.buffer_font_size_settings();
|
||||
let ui_font_size_settings = settings.ui_font_size_settings();
|
||||
let agent_ui_font_size_settings = settings.agent_ui_font_size_settings();
|
||||
let agent_buffer_font_size_settings = settings.agent_buffer_font_size_settings();
|
||||
let theme_name = settings.theme.name(SystemAppearance::global(cx).0);
|
||||
let icon_theme_name = settings.icon_theme.name(SystemAppearance::global(cx).0);
|
||||
let theme_overrides = (
|
||||
settings.experimental_theme_overrides.clone(),
|
||||
settings.theme_overrides.clone(),
|
||||
);
|
||||
|
||||
if buffer_font_size_settings != prev_buffer_font_size_settings {
|
||||
prev_buffer_font_size_settings = buffer_font_size_settings;
|
||||
reset_buffer_font_size(cx);
|
||||
}
|
||||
|
||||
let ui_font_size_settings = ThemeSettings::get_global(cx).ui_font_size_settings();
|
||||
if ui_font_size_settings != prev_ui_font_size_settings {
|
||||
prev_ui_font_size_settings = ui_font_size_settings;
|
||||
reset_ui_font_size(cx);
|
||||
}
|
||||
|
||||
let agent_ui_font_size_settings =
|
||||
ThemeSettings::get_global(cx).agent_ui_font_size_settings();
|
||||
if agent_ui_font_size_settings != prev_agent_ui_font_size_settings {
|
||||
prev_agent_ui_font_size_settings = agent_ui_font_size_settings;
|
||||
reset_agent_ui_font_size(cx);
|
||||
}
|
||||
|
||||
let agent_buffer_font_size_settings =
|
||||
ThemeSettings::get_global(cx).agent_buffer_font_size_settings();
|
||||
if agent_buffer_font_size_settings != prev_agent_buffer_font_size_settings {
|
||||
prev_agent_buffer_font_size_settings = agent_buffer_font_size_settings;
|
||||
reset_agent_buffer_font_size(cx);
|
||||
}
|
||||
|
||||
if theme_name != prev_theme_name || theme_overrides != prev_theme_overrides {
|
||||
prev_theme_name = theme_name;
|
||||
prev_theme_overrides = theme_overrides;
|
||||
GlobalTheme::reload_theme(cx);
|
||||
}
|
||||
|
||||
if icon_theme_name != prev_icon_theme_name {
|
||||
prev_icon_theme_name = icon_theme_name;
|
||||
GlobalTheme::reload_icon_theme(cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -154,7 +184,7 @@ pub trait ActiveTheme {
|
||||
|
||||
impl ActiveTheme for App {
|
||||
fn theme(&self) -> &Arc<Theme> {
|
||||
&ThemeSettings::get_global(self).active_theme
|
||||
GlobalTheme::theme(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,3 +438,82 @@ pub async fn read_icon_theme(
|
||||
|
||||
Ok(icon_theme_family)
|
||||
}
|
||||
|
||||
/// The active theme
|
||||
pub struct GlobalTheme {
|
||||
theme: Arc<Theme>,
|
||||
icon_theme: Arc<IconTheme>,
|
||||
}
|
||||
impl Global for GlobalTheme {}
|
||||
|
||||
impl GlobalTheme {
|
||||
fn configured_theme(cx: &mut App) -> Arc<Theme> {
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
let theme_settings = ThemeSettings::get_global(cx);
|
||||
let system_appearance = SystemAppearance::global(cx);
|
||||
|
||||
let theme_name = theme_settings.theme.name(*system_appearance);
|
||||
|
||||
let theme = match themes.get(&theme_name.0) {
|
||||
Ok(theme) => theme,
|
||||
Err(err) => {
|
||||
if themes.extensions_loaded() {
|
||||
log::error!("{err}");
|
||||
}
|
||||
themes
|
||||
.get(default_theme(*system_appearance))
|
||||
// fallback for tests.
|
||||
.unwrap_or_else(|_| themes.get(DEFAULT_DARK_THEME).unwrap())
|
||||
}
|
||||
};
|
||||
theme_settings.apply_theme_overrides(theme)
|
||||
}
|
||||
|
||||
/// Reloads the current theme.
|
||||
///
|
||||
/// Reads the [`ThemeSettings`] to know which theme should be loaded,
|
||||
/// taking into account the current [`SystemAppearance`].
|
||||
pub fn reload_theme(cx: &mut App) {
|
||||
let theme = Self::configured_theme(cx);
|
||||
cx.update_global::<Self, _>(|this, _| this.theme = theme);
|
||||
cx.refresh_windows();
|
||||
}
|
||||
|
||||
fn configured_icon_theme(cx: &mut App) -> Arc<IconTheme> {
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
let theme_settings = ThemeSettings::get_global(cx);
|
||||
let system_appearance = SystemAppearance::global(cx);
|
||||
|
||||
let icon_theme_name = theme_settings.icon_theme.name(*system_appearance);
|
||||
|
||||
match themes.get_icon_theme(&icon_theme_name.0) {
|
||||
Ok(theme) => theme,
|
||||
Err(err) => {
|
||||
if themes.extensions_loaded() {
|
||||
log::error!("{err}");
|
||||
}
|
||||
themes.get_icon_theme(DEFAULT_ICON_THEME_NAME).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reloads the current icon theme.
|
||||
///
|
||||
/// Reads the [`ThemeSettings`] to know which icon theme should be loaded,
|
||||
/// taking into account the current [`SystemAppearance`].
|
||||
pub fn reload_icon_theme(cx: &mut App) {
|
||||
let icon_theme = Self::configured_icon_theme(cx);
|
||||
cx.update_global::<Self, _>(|this, _| this.icon_theme = icon_theme);
|
||||
cx.refresh_windows();
|
||||
}
|
||||
|
||||
/// the active theme
|
||||
pub fn theme(cx: &App) -> &Arc<Theme> {
|
||||
&cx.global::<Self>().theme
|
||||
}
|
||||
|
||||
/// the active icon theme
|
||||
pub fn icon_theme(cx: &App) -> &Arc<IconTheme> {
|
||||
&cx.global::<Self>().icon_theme
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user