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