color.rs

  1pub use crate::{old_theme, ButtonVariant, ElementExt, Theme};
  2use gpui2::{rgb, Hsla, WindowContext};
  3use strum::EnumIter;
  4
  5#[derive(Clone, Copy)]
  6pub struct PlayerThemeColors {
  7    pub cursor: Hsla,
  8    pub selection: Hsla,
  9}
 10
 11impl std::fmt::Debug for PlayerThemeColors {
 12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 13        f.debug_struct("PlayerThemeColors")
 14            .field("cursor", &self.cursor.to_rgb().to_hex())
 15            .field("selection", &self.selection.to_rgb().to_hex())
 16            .finish()
 17    }
 18}
 19
 20impl PlayerThemeColors {
 21    pub fn new(cx: &WindowContext, ix: usize) -> Self {
 22        let theme = old_theme(cx);
 23
 24        if ix < theme.players.len() {
 25            Self {
 26                cursor: theme.players[ix].cursor,
 27                selection: theme.players[ix].selection,
 28            }
 29        } else {
 30            Self {
 31                cursor: rgb::<Hsla>(0xff00ff),
 32                selection: rgb::<Hsla>(0xff00ff),
 33            }
 34        }
 35    }
 36}
 37
 38#[derive(Clone, Copy)]
 39pub struct SyntaxColor {
 40    pub comment: Hsla,
 41    pub string: Hsla,
 42    pub function: Hsla,
 43    pub keyword: Hsla,
 44}
 45
 46impl std::fmt::Debug for SyntaxColor {
 47    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 48        f.debug_struct("SyntaxColor")
 49            .field("comment", &self.comment.to_rgb().to_hex())
 50            .field("string", &self.string.to_rgb().to_hex())
 51            .field("function", &self.function.to_rgb().to_hex())
 52            .field("keyword", &self.keyword.to_rgb().to_hex())
 53            .finish()
 54    }
 55}
 56
 57impl SyntaxColor {
 58    pub fn new(cx: &WindowContext) -> Self {
 59        let theme = old_theme(cx);
 60
 61        Self {
 62            comment: theme
 63                .syntax
 64                .get("comment")
 65                .cloned()
 66                .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
 67            string: theme
 68                .syntax
 69                .get("string")
 70                .cloned()
 71                .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
 72            function: theme
 73                .syntax
 74                .get("function")
 75                .cloned()
 76                .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
 77            keyword: theme
 78                .syntax
 79                .get("keyword")
 80                .cloned()
 81                .unwrap_or_else(|| rgb::<Hsla>(0xff00ff)),
 82        }
 83    }
 84}
 85
 86/// ThemeColor is the primary interface for coloring elements in the UI.
 87///
 88/// It is a mapping layer between semantic theme colors and colors from the reference library.
 89///
 90/// While we are between zed and zed2 we use this to map semantic colors to the old theme.
 91#[derive(Clone, Copy)]
 92pub struct ThemeColor {
 93    pub transparent: Hsla,
 94    pub mac_os_traffic_light_red: Hsla,
 95    pub mac_os_traffic_light_yellow: Hsla,
 96    pub mac_os_traffic_light_green: Hsla,
 97    pub border: Hsla,
 98    pub border_variant: Hsla,
 99    pub border_focused: Hsla,
100    pub border_transparent: Hsla,
101    /// The background color of an elevated surface, like a modal, tooltip or toast.
102    pub elevated_surface: Hsla,
103    pub surface: Hsla,
104    /// Window background color of the base app
105    pub background: Hsla,
106    /// Default background for elements like filled buttons,
107    /// text fields, checkboxes, radio buttons, etc.
108    /// - TODO: Map to step 3.
109    pub filled_element: Hsla,
110    /// The background color of a hovered element, like a button being hovered
111    /// with a mouse, or hovered on a touch screen.
112    /// - TODO: Map to step 4.
113    pub filled_element_hover: Hsla,
114    /// The background color of an active element, like a button being pressed,
115    /// or tapped on a touch screen.
116    /// - TODO: Map to step 5.
117    pub filled_element_active: Hsla,
118    /// The background color of a selected element, like a selected tab,
119    /// a button toggled on, or a checkbox that is checked.
120    pub filled_element_selected: Hsla,
121    pub filled_element_disabled: Hsla,
122    pub ghost_element: Hsla,
123    /// The background color of a hovered element with no default background,
124    /// like a ghost-style button or an interactable list item.
125    /// - TODO: Map to step 3.
126    pub ghost_element_hover: Hsla,
127    /// - TODO: Map to step 4.
128    pub ghost_element_active: Hsla,
129    pub ghost_element_selected: Hsla,
130    pub ghost_element_disabled: Hsla,
131    pub text: Hsla,
132    pub text_muted: Hsla,
133    pub text_placeholder: Hsla,
134    pub text_disabled: Hsla,
135    pub text_accent: Hsla,
136    pub icon_muted: Hsla,
137    pub syntax: SyntaxColor,
138
139    pub status_bar: Hsla,
140    pub title_bar: Hsla,
141    pub toolbar: Hsla,
142    pub tab_bar: Hsla,
143    /// The background of the editor
144    pub editor: Hsla,
145    pub editor_subheader: Hsla,
146    pub editor_active_line: Hsla,
147    pub terminal: Hsla,
148    pub image_fallback_background: Hsla,
149
150    pub git_created: Hsla,
151    pub git_modified: Hsla,
152    pub git_deleted: Hsla,
153    pub git_conflict: Hsla,
154    pub git_ignored: Hsla,
155    pub git_renamed: Hsla,
156
157    pub players: [PlayerThemeColors; 8],
158}
159
160impl std::fmt::Debug for ThemeColor {
161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162        f.debug_struct("ThemeColor")
163            .field("transparent", &self.transparent.to_rgb().to_hex())
164            .field(
165                "mac_os_traffic_light_red",
166                &self.mac_os_traffic_light_red.to_rgb().to_hex(),
167            )
168            .field(
169                "mac_os_traffic_light_yellow",
170                &self.mac_os_traffic_light_yellow.to_rgb().to_hex(),
171            )
172            .field(
173                "mac_os_traffic_light_green",
174                &self.mac_os_traffic_light_green.to_rgb().to_hex(),
175            )
176            .field("border", &self.border.to_rgb().to_hex())
177            .field("border_variant", &self.border_variant.to_rgb().to_hex())
178            .field("border_focused", &self.border_focused.to_rgb().to_hex())
179            .field(
180                "border_transparent",
181                &self.border_transparent.to_rgb().to_hex(),
182            )
183            .field("elevated_surface", &self.elevated_surface.to_rgb().to_hex())
184            .field("surface", &self.surface.to_rgb().to_hex())
185            .field("background", &self.background.to_rgb().to_hex())
186            .field("filled_element", &self.filled_element.to_rgb().to_hex())
187            .field(
188                "filled_element_hover",
189                &self.filled_element_hover.to_rgb().to_hex(),
190            )
191            .field(
192                "filled_element_active",
193                &self.filled_element_active.to_rgb().to_hex(),
194            )
195            .field(
196                "filled_element_selected",
197                &self.filled_element_selected.to_rgb().to_hex(),
198            )
199            .field(
200                "filled_element_disabled",
201                &self.filled_element_disabled.to_rgb().to_hex(),
202            )
203            .field("ghost_element", &self.ghost_element.to_rgb().to_hex())
204            .field(
205                "ghost_element_hover",
206                &self.ghost_element_hover.to_rgb().to_hex(),
207            )
208            .field(
209                "ghost_element_active",
210                &self.ghost_element_active.to_rgb().to_hex(),
211            )
212            .field(
213                "ghost_element_selected",
214                &self.ghost_element_selected.to_rgb().to_hex(),
215            )
216            .field(
217                "ghost_element_disabled",
218                &self.ghost_element_disabled.to_rgb().to_hex(),
219            )
220            .field("text", &self.text.to_rgb().to_hex())
221            .field("text_muted", &self.text_muted.to_rgb().to_hex())
222            .field("text_placeholder", &self.text_placeholder.to_rgb().to_hex())
223            .field("text_disabled", &self.text_disabled.to_rgb().to_hex())
224            .field("text_accent", &self.text_accent.to_rgb().to_hex())
225            .field("icon_muted", &self.icon_muted.to_rgb().to_hex())
226            .field("syntax", &self.syntax)
227            .field("status_bar", &self.status_bar.to_rgb().to_hex())
228            .field("title_bar", &self.title_bar.to_rgb().to_hex())
229            .field("toolbar", &self.toolbar.to_rgb().to_hex())
230            .field("tab_bar", &self.tab_bar.to_rgb().to_hex())
231            .field("editor", &self.editor.to_rgb().to_hex())
232            .field("editor_subheader", &self.editor_subheader.to_rgb().to_hex())
233            .field(
234                "editor_active_line",
235                &self.editor_active_line.to_rgb().to_hex(),
236            )
237            .field("terminal", &self.terminal.to_rgb().to_hex())
238            .field(
239                "image_fallback_background",
240                &self.image_fallback_background.to_rgb().to_hex(),
241            )
242            .field("git_created", &self.git_created.to_rgb().to_hex())
243            .field("git_modified", &self.git_modified.to_rgb().to_hex())
244            .field("git_deleted", &self.git_deleted.to_rgb().to_hex())
245            .field("git_conflict", &self.git_conflict.to_rgb().to_hex())
246            .field("git_ignored", &self.git_ignored.to_rgb().to_hex())
247            .field("git_renamed", &self.git_renamed.to_rgb().to_hex())
248            .field("players", &self.players)
249            .finish()
250    }
251}
252
253/// Colors used exclusively for syntax highlighting.
254///
255/// For now we deserialize these from a theme.
256/// These will be defined statically in the new theme.
257#[derive(Default, PartialEq, EnumIter, Clone, Copy)]
258pub enum HighlightColor {
259    #[default]
260    Default,
261    Comment,
262    String,
263    Function,
264    Keyword,
265}
266
267impl HighlightColor {
268    pub fn hsla(&self, theme: &Theme) -> Hsla {
269        match self {
270            Self::Default => theme
271                .syntax
272                .get("primary")
273                .cloned()
274                .expect("Couldn't find `primary` in theme.syntax"),
275            Self::Comment => theme
276                .syntax
277                .get("comment")
278                .cloned()
279                .expect("Couldn't find `comment` in theme.syntax"),
280            Self::String => theme
281                .syntax
282                .get("string")
283                .cloned()
284                .expect("Couldn't find `string` in theme.syntax"),
285            Self::Function => theme
286                .syntax
287                .get("function")
288                .cloned()
289                .expect("Couldn't find `function` in theme.syntax"),
290            Self::Keyword => theme
291                .syntax
292                .get("keyword")
293                .cloned()
294                .expect("Couldn't find `keyword` in theme.syntax"),
295        }
296    }
297}