Skip to main content

ui/
color.rs

1//! Color picking: a preset [`Swatch`] set the app configures, and
2//! [`ColorPicker`] for anything outside it.
3//!
4//! The set is read through [`crate::AppExt::color_swatches`] and replaced with
5//! [`crate::AppExt::set_color_swatches`]; until then it is [`default_swatches`].
6
7mod picker;
8
9use std::rc::Rc;
10
11use gpui::{App, Global, Hsla, SharedString};
12use theme::{Appearance, Theme};
13
14pub use picker::{ColorPicker, ColorPickerEvent, parse_hex, to_hex};
15
16/// One preset color, with a value per appearance.
17#[derive(Clone, Debug, PartialEq)]
18pub struct Swatch {
19    /// What a tooltip or an accessibility label calls it.
20    pub name: SharedString,
21    pub light: Hsla,
22    pub dark: Hsla,
23}
24
25impl Swatch {
26    pub fn new(
27        name: impl Into<SharedString>,
28        light: impl Into<Hsla>,
29        dark: impl Into<Hsla>,
30    ) -> Self {
31        Self {
32            name: name.into(),
33            light: light.into(),
34            dark: dark.into(),
35        }
36    }
37
38    /// The same color under both appearances.
39    pub fn fixed(name: impl Into<SharedString>, color: impl Into<Hsla>) -> Self {
40        let color = color.into();
41        Self::new(name, color, color)
42    }
43
44    /// The value for `theme`'s appearance.
45    pub fn resolve(&self, theme: &Theme) -> Hsla {
46        match theme.appearance {
47            Appearance::Light => self.light,
48            Appearance::Dark => self.dark,
49        }
50    }
51}
52
53/// Apple's macOS system colors, red through brown.
54pub fn default_swatches() -> Rc<[Swatch]> {
55    let swatch = |name: &'static str, light: u32, dark: u32| {
56        Swatch::new(name, gpui::rgb(light), gpui::rgb(dark))
57    };
58    Rc::from([
59        swatch("Red", 0xFF3B30, 0xFF453A),
60        swatch("Orange", 0xFF9500, 0xFF9F0A),
61        swatch("Yellow", 0xFFCC00, 0xFFD60A),
62        swatch("Green", 0x28CD41, 0x32D74B),
63        swatch("Mint", 0x00C7BE, 0x63E6E2),
64        swatch("Teal", 0x59ADC4, 0x6AC4DC),
65        swatch("Cyan", 0x55BEF0, 0x5AC8F5),
66        swatch("Blue", 0x007AFF, 0x0A84FF),
67        swatch("Indigo", 0x5856D6, 0x5E5CE6),
68        swatch("Purple", 0xAF52DE, 0xBF5AF2),
69        swatch("Pink", 0xFF2D55, 0xFF375F),
70        swatch("Brown", 0xA2845E, 0xAC8E68),
71    ])
72}
73
74struct Swatches(Rc<[Swatch]>);
75
76impl Global for Swatches {}
77
78pub(crate) fn swatches(cx: &App) -> Rc<[Swatch]> {
79    cx.try_global::<Swatches>()
80        .map_or_else(default_swatches, |set| set.0.clone())
81}
82
83pub(crate) fn set_swatches(set: impl Into<Rc<[Swatch]>>, cx: &mut App) {
84    cx.set_global(Swatches(set.into()));
85    cx.refresh_windows();
86}