#![deny(missing_docs)] //! # Theme //! //! This crate provides the theme system for Zed. //! //! ## Overview //! //! A theme is a collection of colors used to build a consistent appearance for UI components across the application. mod default_colors; mod fallback_themes; mod font_family_cache; mod registry; mod scale; mod schema; mod settings; mod styles; use std::sync::Arc; use ::settings::{Settings, SettingsStore}; pub use default_colors::*; pub use font_family_cache::*; pub use registry::*; pub use scale::*; pub use schema::*; pub use settings::*; pub use styles::*; use gpui::{ px, AppContext, AssetSource, Hsla, Pixels, SharedString, WindowAppearance, WindowBackgroundAppearance, }; use serde::Deserialize; /// Defines window border radius for platforms that use client side decorations. pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0); /// Defines window shadow size for platforms that use client side decorations. pub const CLIENT_SIDE_DECORATION_SHADOW: Pixels = px(10.0); /// The appearance of the theme. #[derive(Debug, PartialEq, Clone, Copy, Deserialize)] pub enum Appearance { /// A light appearance. Light, /// A dark appearance. Dark, } impl Appearance { /// Returns whether the appearance is light. pub fn is_light(&self) -> bool { match self { Self::Light => true, Self::Dark => false, } } } impl From for Appearance { fn from(value: WindowAppearance) -> Self { match value { WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::Dark, WindowAppearance::Light | WindowAppearance::VibrantLight => Self::Light, } } } /// Which themes should be loaded. This is used primarlily for testing. pub enum LoadThemes { /// Only load the base theme. /// /// No user themes will be loaded. JustBase, /// Load all of the built-in themes. All(Box), } /// Initialize the theme system. pub fn init(themes_to_load: LoadThemes, cx: &mut AppContext) { let (assets, load_user_themes) = match themes_to_load { LoadThemes::JustBase => (Box::new(()) as Box, false), LoadThemes::All(assets) => (assets, true), }; ThemeRegistry::set_global(assets, cx); if load_user_themes { ThemeRegistry::global(cx).load_bundled_themes(); } ThemeSettings::register(cx); FontFamilyCache::init_global(cx); let mut prev_buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size; cx.observe_global::(move |cx| { let buffer_font_size = ThemeSettings::get_global(cx).buffer_font_size; if buffer_font_size != prev_buffer_font_size { prev_buffer_font_size = buffer_font_size; reset_buffer_font_size(cx); } }) .detach(); } /// Implementing this trait allows accessing the active theme. pub trait ActiveTheme { /// Returns the active theme. fn theme(&self) -> &Arc; } impl ActiveTheme for AppContext { fn theme(&self) -> &Arc { &ThemeSettings::get_global(self).active_theme } } /// A theme family is a grouping of themes under a single name. /// /// For example, the "One" theme family contains the "One Light" and "One Dark" themes. /// /// It can also be used to package themes with many variants. /// /// For example, the "Atelier" theme family contains "Cave", "Dune", "Estuary", "Forest", "Heath", etc. pub struct ThemeFamily { /// The unique identifier for the theme family. pub id: String, /// The name of the theme family. This will be displayed in the UI, such as when adding or removing a theme family. pub name: SharedString, /// The author of the theme family. pub author: SharedString, /// The [Theme]s in the family. pub themes: Vec, /// The color scales used by the themes in the family. /// Note: This will be removed in the future. pub scales: ColorScales, } impl ThemeFamily {} /// A theme is the primary mechanism for defining the appearance of the UI. #[derive(Clone)] pub struct Theme { /// The unique identifier for the theme. pub id: String, /// The name of the theme. pub name: SharedString, /// The appearance of the theme (light or dark). pub appearance: Appearance, /// The colors and other styles for the theme. pub styles: ThemeStyles, } impl Theme { /// Returns the [`SystemColors`] for the theme. #[inline(always)] pub fn system(&self) -> &SystemColors { &self.styles.system } /// Returns the [`AccentColors`] for the theme. #[inline(always)] pub fn accents(&self) -> &AccentColors { &self.styles.accents } /// Returns the [`PlayerColors`] for the theme. #[inline(always)] pub fn players(&self) -> &PlayerColors { &self.styles.player } /// Returns the [`ThemeColors`] for the theme. #[inline(always)] pub fn colors(&self) -> &ThemeColors { &self.styles.colors } /// Returns the [`SyntaxTheme`] for the theme. #[inline(always)] pub fn syntax(&self) -> &Arc { &self.styles.syntax } /// Returns the [`StatusColors`] for the theme. #[inline(always)] pub fn status(&self) -> &StatusColors { &self.styles.status } /// Returns the color for the syntax node with the given name. #[inline(always)] pub fn syntax_color(&self, name: &str) -> Hsla { self.syntax().color(name) } /// Returns the [`Appearance`] for the theme. #[inline(always)] pub fn appearance(&self) -> Appearance { self.appearance } /// Returns the [`WindowBackgroundAppearance`] for the theme. #[inline(always)] pub fn window_background_appearance(&self) -> WindowBackgroundAppearance { self.styles.window_background_appearance } } /// Compounds a color with an alpha value. /// TODO: Replace this with a method on Hsla. pub fn color_alpha(color: Hsla, alpha: f32) -> Hsla { let mut color = color; color.a = alpha; color }