1use std::collections::HashMap;
2
3use gpui2::{AppContext, Hsla};
4
5use crate::{theme, Appearance};
6
7#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum ColorScaleName {
9 Gray,
10 Mauve,
11 Slate,
12 Sage,
13 Olive,
14 Sand,
15 Gold,
16 Bronze,
17 Brown,
18 Yellow,
19 Amber,
20 Orange,
21 Tomato,
22 Red,
23 Ruby,
24 Crimson,
25 Pink,
26 Plum,
27 Purple,
28 Violet,
29 Iris,
30 Indigo,
31 Blue,
32 Cyan,
33 Teal,
34 Jade,
35 Green,
36 Grass,
37 Lime,
38 Mint,
39 Sky,
40 Black,
41 White,
42}
43
44impl std::fmt::Display for ColorScaleName {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(
47 f,
48 "{}",
49 match self {
50 Self::Gray => "Gray",
51 Self::Mauve => "Mauve",
52 Self::Slate => "Slate",
53 Self::Sage => "Sage",
54 Self::Olive => "Olive",
55 Self::Sand => "Sand",
56 Self::Gold => "Gold",
57 Self::Bronze => "Bronze",
58 Self::Brown => "Brown",
59 Self::Yellow => "Yellow",
60 Self::Amber => "Amber",
61 Self::Orange => "Orange",
62 Self::Tomato => "Tomato",
63 Self::Red => "Red",
64 Self::Ruby => "Ruby",
65 Self::Crimson => "Crimson",
66 Self::Pink => "Pink",
67 Self::Plum => "Plum",
68 Self::Purple => "Purple",
69 Self::Violet => "Violet",
70 Self::Iris => "Iris",
71 Self::Indigo => "Indigo",
72 Self::Blue => "Blue",
73 Self::Cyan => "Cyan",
74 Self::Teal => "Teal",
75 Self::Jade => "Jade",
76 Self::Green => "Green",
77 Self::Grass => "Grass",
78 Self::Lime => "Lime",
79 Self::Mint => "Mint",
80 Self::Sky => "Sky",
81 Self::Black => "Black",
82 Self::White => "White",
83 }
84 )
85 }
86}
87
88pub type ColorScale = [Hsla; 12];
89
90pub type ColorScales = HashMap<ColorScaleName, ColorScaleSet>;
91
92pub struct ColorScaleSet {
93 name: ColorScaleName,
94 light: ColorScale,
95 dark: ColorScale,
96 light_alpha: ColorScale,
97 dark_alpha: ColorScale,
98}
99
100impl ColorScaleSet {
101 pub fn new(
102 name: ColorScaleName,
103 light: ColorScale,
104 light_alpha: ColorScale,
105 dark: ColorScale,
106 dark_alpha: ColorScale,
107 ) -> Self {
108 Self {
109 name,
110 light,
111 light_alpha,
112 dark,
113 dark_alpha,
114 }
115 }
116
117 pub fn name(&self) -> String {
118 self.name.to_string()
119 }
120
121 pub fn light(&self, step: usize) -> Hsla {
122 self.light[step - 1]
123 }
124
125 pub fn light_alpha(&self, step: usize) -> Hsla {
126 self.light_alpha[step - 1]
127 }
128
129 pub fn dark(&self, step: usize) -> Hsla {
130 self.dark[step - 1]
131 }
132
133 pub fn dark_alpha(&self, step: usize) -> Hsla {
134 self.dark[step - 1]
135 }
136
137 fn current_appearance(cx: &AppContext) -> Appearance {
138 let theme = theme(cx);
139 if theme.metadata.is_light {
140 Appearance::Light
141 } else {
142 Appearance::Dark
143 }
144 }
145
146 /// Returns the one-based step in the scale.
147 ///
148 /// We usually reference steps as 1-12 instead of 0-11, so we
149 /// automatically subtract 1 from the index.
150 pub fn step(self, cx: &AppContext, index: usize) -> Hsla {
151 let appearance = Self::current_appearance(cx);
152
153 match appearance {
154 Appearance::Light => self.light(index),
155 Appearance::Dark => self.dark(index),
156 }
157 }
158
159 pub fn step_alpha(self, cx: &AppContext, index: usize) -> Hsla {
160 let appearance = Self::current_appearance(cx);
161 match appearance {
162 Appearance::Light => self.light_alpha(index),
163 Appearance::Dark => self.dark_alpha(index),
164 }
165 }
166}