1//! # Theme
2//!
3//! This crate provides the theme system for Zed.
4//!
5//! ## Overview
6//!
7//! A theme is a collection of colors used to build a consistent appearance for UI components across the application.
8
9mod default_colors;
10mod default_theme;
11mod one_themes;
12pub mod prelude;
13mod registry;
14mod scale;
15mod schema;
16mod settings;
17mod styles;
18
19use std::sync::Arc;
20
21use ::settings::{Settings, SettingsStore};
22pub use default_colors::*;
23pub use default_theme::*;
24pub use registry::*;
25pub use scale::*;
26pub use schema::*;
27pub use settings::*;
28pub use styles::*;
29
30use gpui::{AppContext, AssetSource, Hsla, SharedString, WindowAppearance};
31use serde::Deserialize;
32
33#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
34pub enum Appearance {
35 Light,
36 Dark,
37}
38
39impl Appearance {
40 pub fn is_light(&self) -> bool {
41 match self {
42 Self::Light => true,
43 Self::Dark => false,
44 }
45 }
46}
47
48impl From<WindowAppearance> for Appearance {
49 fn from(value: WindowAppearance) -> Self {
50 match value {
51 WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::Dark,
52 WindowAppearance::Light | WindowAppearance::VibrantLight => Self::Light,
53 }
54 }
55}
56
57pub enum LoadThemes {
58 /// Only load the base theme.
59 ///
60 /// No user themes will be loaded.
61 JustBase,
62
63 /// Load all of the built-in themes.
64 All(Box<dyn AssetSource>),
65}
66
67pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) {
68 let (assets, load_user_themes) = match themes_to_load {
69 LoadThemes::JustBase => (Box::new(()) as Box<dyn AssetSource>, false),
70 LoadThemes::All(assets) => (assets, true),
71 };
72 ThemeRegistry::set_global(assets, cx);
73
74 if load_user_themes {
75 ThemeRegistry::global(cx).load_bundled_themes();
76 }
77
78 ThemeSettings::register(cx);
79
80 let mut prev_buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
81 cx.observe_global::<SettingsStore>(move |cx| {
82 let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size;
83 if buffer_font_size != prev_buffer_font_size {
84 prev_buffer_font_size = buffer_font_size;
85 reset_font_size(cx);
86 }
87 })
88 .detach();
89}
90
91pub trait ActiveTheme {
92 fn theme(&self) -> &Arc<Theme>;
93}
94
95impl ActiveTheme for AppContext {
96 fn theme(&self) -> &Arc<Theme> {
97 &ThemeSettings::get_global(self).active_theme
98 }
99}
100
101pub struct ThemeFamily {
102 pub id: String,
103 pub name: SharedString,
104 pub author: SharedString,
105 pub themes: Vec<Theme>,
106 pub scales: ColorScales,
107}
108
109impl ThemeFamily {}
110
111#[derive(Clone)]
112pub struct Theme {
113 pub id: String,
114 pub name: SharedString,
115 pub appearance: Appearance,
116 pub styles: ThemeStyles,
117}
118
119impl Theme {
120 /// Returns the [`SystemColors`] for the theme.
121 #[inline(always)]
122 pub fn system(&self) -> &SystemColors {
123 &self.styles.system
124 }
125
126 /// Returns the [`PlayerColors`] for the theme.
127 #[inline(always)]
128 pub fn players(&self) -> &PlayerColors {
129 &self.styles.player
130 }
131
132 /// Returns the [`ThemeColors`] for the theme.
133 #[inline(always)]
134 pub fn colors(&self) -> &ThemeColors {
135 &self.styles.colors
136 }
137
138 /// Returns the [`SyntaxTheme`] for the theme.
139 #[inline(always)]
140 pub fn syntax(&self) -> &Arc<SyntaxTheme> {
141 &self.styles.syntax
142 }
143
144 /// Returns the [`StatusColors`] for the theme.
145 #[inline(always)]
146 pub fn status(&self) -> &StatusColors {
147 &self.styles.status
148 }
149
150 /// Returns the color for the syntax node with the given name.
151 #[inline(always)]
152 pub fn syntax_color(&self, name: &str) -> Hsla {
153 self.syntax().color(name)
154 }
155
156 /// Returns the [`Appearance`] for the theme.
157 #[inline(always)]
158 pub fn appearance(&self) -> Appearance {
159 self.appearance
160 }
161}
162
163pub fn color_alpha(color: Hsla, alpha: f32) -> Hsla {
164 let mut color = color;
165 color.a = alpha;
166 color
167}