1use gpui::{AppContext, Hsla, SharedString};
2
3use crate::{ActiveTheme, Appearance};
4
5/// A one-based step in a [`ColorScale`].
6#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
7pub struct ColorScaleStep(usize);
8
9impl ColorScaleStep {
10 /// The first step in a [`ColorScale`].
11 pub const ONE: Self = Self(1);
12
13 /// The second step in a [`ColorScale`].
14 pub const TWO: Self = Self(2);
15
16 /// The third step in a [`ColorScale`].
17 pub const THREE: Self = Self(3);
18
19 /// The fourth step in a [`ColorScale`].
20 pub const FOUR: Self = Self(4);
21
22 /// The fifth step in a [`ColorScale`].
23 pub const FIVE: Self = Self(5);
24
25 /// The sixth step in a [`ColorScale`].
26 pub const SIX: Self = Self(6);
27
28 /// The seventh step in a [`ColorScale`].
29 pub const SEVEN: Self = Self(7);
30
31 /// The eighth step in a [`ColorScale`].
32 pub const EIGHT: Self = Self(8);
33
34 /// The ninth step in a [`ColorScale`].
35 pub const NINE: Self = Self(9);
36
37 /// The tenth step in a [`ColorScale`].
38 pub const TEN: Self = Self(10);
39
40 /// The eleventh step in a [`ColorScale`].
41 pub const ELEVEN: Self = Self(11);
42
43 /// The twelfth step in a [`ColorScale`].
44 pub const TWELVE: Self = Self(12);
45
46 /// All of the steps in a [`ColorScale`].
47 pub const ALL: [ColorScaleStep; 12] = [
48 Self::ONE,
49 Self::TWO,
50 Self::THREE,
51 Self::FOUR,
52 Self::FIVE,
53 Self::SIX,
54 Self::SEVEN,
55 Self::EIGHT,
56 Self::NINE,
57 Self::TEN,
58 Self::ELEVEN,
59 Self::TWELVE,
60 ];
61}
62
63pub struct ColorScale(Vec<Hsla>);
64
65impl FromIterator<Hsla> for ColorScale {
66 fn from_iter<T: IntoIterator<Item = Hsla>>(iter: T) -> Self {
67 Self(Vec::from_iter(iter))
68 }
69}
70
71impl ColorScale {
72 /// Returns the specified step in the [`ColorScale`].
73 #[inline]
74 pub fn step(&self, step: ColorScaleStep) -> Hsla {
75 // Steps are one-based, so we need convert to the zero-based vec index.
76 self.0[step.0 - 1]
77 }
78
79 /// Returns the first step in the [`ColorScale`].
80 #[inline]
81 pub fn step_1(&self) -> Hsla {
82 self.step(ColorScaleStep::ONE)
83 }
84
85 /// Returns the second step in the [`ColorScale`].
86 #[inline]
87 pub fn step_2(&self) -> Hsla {
88 self.step(ColorScaleStep::TWO)
89 }
90
91 /// Returns the third step in the [`ColorScale`].
92 #[inline]
93 pub fn step_3(&self) -> Hsla {
94 self.step(ColorScaleStep::THREE)
95 }
96
97 /// Returns the fourth step in the [`ColorScale`].
98 #[inline]
99 pub fn step_4(&self) -> Hsla {
100 self.step(ColorScaleStep::FOUR)
101 }
102
103 /// Returns the fifth step in the [`ColorScale`].
104 #[inline]
105 pub fn step_5(&self) -> Hsla {
106 self.step(ColorScaleStep::FIVE)
107 }
108
109 /// Returns the sixth step in the [`ColorScale`].
110 #[inline]
111 pub fn step_6(&self) -> Hsla {
112 self.step(ColorScaleStep::SIX)
113 }
114
115 /// Returns the seventh step in the [`ColorScale`].
116 #[inline]
117 pub fn step_7(&self) -> Hsla {
118 self.step(ColorScaleStep::SEVEN)
119 }
120
121 /// Returns the eighth step in the [`ColorScale`].
122 #[inline]
123 pub fn step_8(&self) -> Hsla {
124 self.step(ColorScaleStep::EIGHT)
125 }
126
127 /// Returns the ninth step in the [`ColorScale`].
128 #[inline]
129 pub fn step_9(&self) -> Hsla {
130 self.step(ColorScaleStep::NINE)
131 }
132
133 /// Returns the tenth step in the [`ColorScale`].
134 #[inline]
135 pub fn step_10(&self) -> Hsla {
136 self.step(ColorScaleStep::TEN)
137 }
138
139 /// Returns the eleventh step in the [`ColorScale`].
140 #[inline]
141 pub fn step_11(&self) -> Hsla {
142 self.step(ColorScaleStep::ELEVEN)
143 }
144
145 /// Returns the twelfth step in the [`ColorScale`].
146 #[inline]
147 pub fn step_12(&self) -> Hsla {
148 self.step(ColorScaleStep::TWELVE)
149 }
150}
151
152pub struct ColorScales {
153 pub gray: ColorScaleSet,
154 pub mauve: ColorScaleSet,
155 pub slate: ColorScaleSet,
156 pub sage: ColorScaleSet,
157 pub olive: ColorScaleSet,
158 pub sand: ColorScaleSet,
159 pub gold: ColorScaleSet,
160 pub bronze: ColorScaleSet,
161 pub brown: ColorScaleSet,
162 pub yellow: ColorScaleSet,
163 pub amber: ColorScaleSet,
164 pub orange: ColorScaleSet,
165 pub tomato: ColorScaleSet,
166 pub red: ColorScaleSet,
167 pub ruby: ColorScaleSet,
168 pub crimson: ColorScaleSet,
169 pub pink: ColorScaleSet,
170 pub plum: ColorScaleSet,
171 pub purple: ColorScaleSet,
172 pub violet: ColorScaleSet,
173 pub iris: ColorScaleSet,
174 pub indigo: ColorScaleSet,
175 pub blue: ColorScaleSet,
176 pub cyan: ColorScaleSet,
177 pub teal: ColorScaleSet,
178 pub jade: ColorScaleSet,
179 pub green: ColorScaleSet,
180 pub grass: ColorScaleSet,
181 pub lime: ColorScaleSet,
182 pub mint: ColorScaleSet,
183 pub sky: ColorScaleSet,
184 pub black: ColorScaleSet,
185 pub white: ColorScaleSet,
186}
187
188impl IntoIterator for ColorScales {
189 type Item = ColorScaleSet;
190
191 type IntoIter = std::vec::IntoIter<Self::Item>;
192
193 fn into_iter(self) -> Self::IntoIter {
194 vec![
195 self.gray,
196 self.mauve,
197 self.slate,
198 self.sage,
199 self.olive,
200 self.sand,
201 self.gold,
202 self.bronze,
203 self.brown,
204 self.yellow,
205 self.amber,
206 self.orange,
207 self.tomato,
208 self.red,
209 self.ruby,
210 self.crimson,
211 self.pink,
212 self.plum,
213 self.purple,
214 self.violet,
215 self.iris,
216 self.indigo,
217 self.blue,
218 self.cyan,
219 self.teal,
220 self.jade,
221 self.green,
222 self.grass,
223 self.lime,
224 self.mint,
225 self.sky,
226 self.black,
227 self.white,
228 ]
229 .into_iter()
230 }
231}
232
233pub struct ColorScaleSet {
234 name: SharedString,
235 light: ColorScale,
236 dark: ColorScale,
237 light_alpha: ColorScale,
238 dark_alpha: ColorScale,
239}
240
241impl ColorScaleSet {
242 pub fn new(
243 name: impl Into<SharedString>,
244 light: ColorScale,
245 light_alpha: ColorScale,
246 dark: ColorScale,
247 dark_alpha: ColorScale,
248 ) -> Self {
249 Self {
250 name: name.into(),
251 light,
252 light_alpha,
253 dark,
254 dark_alpha,
255 }
256 }
257
258 pub fn name(&self) -> &SharedString {
259 &self.name
260 }
261
262 pub fn light(&self) -> &ColorScale {
263 &self.light
264 }
265
266 pub fn light_alpha(&self) -> &ColorScale {
267 &self.light_alpha
268 }
269
270 pub fn dark(&self) -> &ColorScale {
271 &self.dark
272 }
273
274 pub fn dark_alpha(&self) -> &ColorScale {
275 &self.dark_alpha
276 }
277
278 pub fn step(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
279 match cx.theme().appearance {
280 Appearance::Light => self.light().step(step),
281 Appearance::Dark => self.dark().step(step),
282 }
283 }
284
285 pub fn step_alpha(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
286 match cx.theme().appearance {
287 Appearance::Light => self.light_alpha.step(step),
288 Appearance::Dark => self.dark_alpha.step(step),
289 }
290 }
291}