1#[derive(Debug, Default)]
2pub enum State {
3 Latte,
4 #[default]
5 Frappe,
6 Macchiato,
7 Mocha,
8}
9
10#[derive(Debug, Default)]
11pub struct StateMachine {
12 state: State,
13 theme: Theme,
14 is_latte: bool, }
16
17impl StateMachine {
18 pub fn new() -> Self {
19 Self::default()
20 }
21
22 pub fn set_theme(&mut self, ctx: &egui::Context, theme: &Theme) {
23 StateMachine::update_theme(self, ctx, theme);
24 }
25
26 pub fn rotate_theme(&mut self, ctx: &egui::Context) {
27 match self.state {
28 State::Latte => {
29 self.theme = FRAPPE;
30 self.state = State::Frappe;
31 self.is_latte = false;
32 }
33 State::Frappe => {
34 self.theme = MACCHIATO;
35 self.state = State::Macchiato;
36 self.is_latte = false;
37 }
38 State::Macchiato => {
39 self.theme = MOCHA;
40 self.state = State::Mocha;
41 self.is_latte = false;
42 }
43 State::Mocha => {
44 self.theme = LATTE;
45 self.state = State::Latte;
46 self.is_latte = true;
47 }
48 }
49 StateMachine::update_theme(self, ctx, &self.theme);
50 }
51
52 fn update_theme(&self, ctx: &egui::Context, theme: &Theme) {
53 ctx.set_visuals(egui::Visuals {
54 dark_mode: if self.is_latte { false } else { true },
55 override_text_color: Some(theme.text),
56 widgets: egui::style::Widgets {
57 noninteractive: egui::style::WidgetVisuals {
58 bg_fill: theme.base,
59 weak_bg_fill: theme.base,
60 bg_stroke: egui::Stroke {
61 color: theme.overlay1,
62 width: 1.0,
63 },
64 rounding: egui::Rounding::ZERO,
65 fg_stroke: egui::Stroke {
66 color: theme.text,
67 width: 1.0,
68 },
69 expansion: 0.0,
70 },
71 inactive: egui::style::WidgetVisuals {
72 bg_fill: theme.surface0,
73 weak_bg_fill: theme.surface0,
74 bg_stroke: egui::Stroke {
75 color: theme.overlay1,
76 width: 1.0,
77 },
78 rounding: egui::Rounding::ZERO,
79 fg_stroke: egui::Stroke {
80 color: theme.text,
81 width: 1.0,
82 },
83 expansion: 0.0,
84 },
85 hovered: egui::style::WidgetVisuals {
86 bg_fill: theme.surface2,
87 weak_bg_fill: theme.surface2,
88 bg_stroke: egui::Stroke {
89 color: theme.overlay1,
90 width: 1.0,
91 },
92 rounding: egui::Rounding::ZERO, fg_stroke: egui::Stroke {
94 color: theme.text,
95 width: 1.0,
96 },
97 expansion: 0.0,
98 },
99 active: egui::style::WidgetVisuals {
100 bg_fill: theme.surface1,
101 weak_bg_fill: theme.surface1,
102 bg_stroke: egui::Stroke {
103 color: theme.overlay1,
104 width: 1.0,
105 },
106 rounding: egui::Rounding::ZERO,
107 fg_stroke: egui::Stroke {
108 color: theme.text,
109 width: 1.0,
110 },
111 expansion: 0.0,
112 },
113 open: egui::style::WidgetVisuals {
114 bg_fill: theme.surface0,
115 weak_bg_fill: theme.surface0,
116 bg_stroke: egui::Stroke {
117 color: theme.overlay1,
118 width: 1.0,
119 },
120 rounding: egui::Rounding::ZERO,
121 fg_stroke: egui::Stroke {
122 color: theme.text,
123 width: 1.0,
124 },
125 expansion: 0.0,
126 },
127 },
128 selection: egui::style::Selection {
129 bg_fill: theme
130 .blue
131 .linear_multiply(if self.is_latte { 0.4 } else { 0.2 }),
132 stroke: egui::Stroke {
133 color: theme.overlay1,
134 width: 1.0,
135 },
136 },
137 hyperlink_color: theme.rosewater,
138 faint_bg_color: theme.surface0,
139 extreme_bg_color: theme.crust,
140 code_bg_color: theme.mantle,
141 warn_fg_color: theme.peach,
142 error_fg_color: theme.maroon,
143 window_rounding: egui::Rounding::ZERO,
144 window_shadow: egui::epaint::Shadow {
145 color: theme.base,
146 offset: egui::Vec2 { x: 0.0, y: 0.0 },
147 blur: 0.0,
148 spread: 0.0,
149 },
150 window_fill: theme.base,
151 window_stroke: egui::Stroke {
152 color: theme.overlay1,
153 width: 1.0,
154 },
155 window_highlight_topmost: true,
156 menu_rounding: egui::Rounding::same(4.), panel_fill: theme.base,
158 popup_shadow: egui::epaint::Shadow {
159 color: theme.base,
160 offset: egui::Vec2 { x: 0.0, y: 0.0 },
161 blur: 0.0,
162 spread: 0.0,
163 },
164 resize_corner_size: 0.0,
165 text_cursor: egui::style::TextCursorStyle {
166 stroke: egui::Stroke {
167 width: 2.0,
168 color: theme.overlay1,
169 },
170 preview: false,
171 blink: true,
172 on_duration: 0.5,
173 off_duration: 0.5,
174 },
175 clip_rect_margin: 0.0,
176 button_frame: true,
177 collapsing_header_frame: true,
178 indent_has_left_vline: true,
179 striped: true,
180 slider_trailing_fill: true,
181 handle_shape: egui::style::HandleShape::Circle,
182 interact_cursor: Some(egui::CursorIcon::Default),
183 image_loading_spinners: true,
184 numeric_color_space: egui::style::NumericColorSpace::Linear,
185 });
186 }
187}
188
189#[derive(Debug, Default)]
190pub struct Theme {
191 pub rosewater: egui::Color32,
192 pub flamingo: egui::Color32,
193 pub pink: egui::Color32,
194 pub mauve: egui::Color32,
195 pub red: egui::Color32,
196 pub maroon: egui::Color32,
197 pub peach: egui::Color32,
198 pub yellow: egui::Color32,
199 pub green: egui::Color32,
200 pub teal: egui::Color32,
201 pub sky: egui::Color32,
202 pub sapphire: egui::Color32,
203 pub blue: egui::Color32,
204 pub lavender: egui::Color32,
205 pub text: egui::Color32,
206 pub subtext1: egui::Color32,
207 pub subtext0: egui::Color32,
208 pub overlay2: egui::Color32,
209 pub overlay1: egui::Color32,
210 pub overlay0: egui::Color32,
211 pub surface2: egui::Color32,
212 pub surface1: egui::Color32,
213 pub surface0: egui::Color32,
214 pub base: egui::Color32,
215 pub mantle: egui::Color32,
216 pub crust: egui::Color32,
217}
218
219pub const LATTE: Theme = Theme {
220 rosewater: egui::Color32::from_rgb(220, 138, 120),
221 flamingo: egui::Color32::from_rgb(221, 120, 120),
222 pink: egui::Color32::from_rgb(234, 118, 203),
223 mauve: egui::Color32::from_rgb(136, 57, 239),
224 red: egui::Color32::from_rgb(210, 15, 57),
225 maroon: egui::Color32::from_rgb(230, 69, 83),
226 peach: egui::Color32::from_rgb(254, 100, 11),
227 yellow: egui::Color32::from_rgb(223, 142, 29),
228 green: egui::Color32::from_rgb(64, 160, 43),
229 teal: egui::Color32::from_rgb(23, 146, 153),
230 sky: egui::Color32::from_rgb(4, 165, 229),
231 sapphire: egui::Color32::from_rgb(32, 159, 181),
232 blue: egui::Color32::from_rgb(30, 102, 245),
233 lavender: egui::Color32::from_rgb(114, 135, 253),
234 text: egui::Color32::from_rgb(76, 79, 105),
235 subtext1: egui::Color32::from_rgb(92, 95, 119),
236 subtext0: egui::Color32::from_rgb(108, 111, 133),
237 overlay2: egui::Color32::from_rgb(124, 127, 147),
238 overlay1: egui::Color32::from_rgb(140, 143, 161),
239 overlay0: egui::Color32::from_rgb(156, 160, 176),
240 surface2: egui::Color32::from_rgb(172, 176, 190),
241 surface1: egui::Color32::from_rgb(188, 192, 204),
242 surface0: egui::Color32::from_rgb(204, 208, 218),
243 base: egui::Color32::from_rgb(239, 241, 245),
244 mantle: egui::Color32::from_rgb(230, 233, 239),
245 crust: egui::Color32::from_rgb(220, 224, 232),
246};
247
248pub const FRAPPE: Theme = Theme {
249 rosewater: egui::Color32::from_rgb(242, 213, 207),
250 flamingo: egui::Color32::from_rgb(238, 190, 190),
251 pink: egui::Color32::from_rgb(244, 184, 228),
252 mauve: egui::Color32::from_rgb(202, 158, 230),
253 red: egui::Color32::from_rgb(231, 130, 132),
254 maroon: egui::Color32::from_rgb(234, 153, 156),
255 peach: egui::Color32::from_rgb(239, 159, 118),
256 yellow: egui::Color32::from_rgb(229, 200, 144),
257 green: egui::Color32::from_rgb(166, 209, 137),
258 teal: egui::Color32::from_rgb(129, 200, 190),
259 sky: egui::Color32::from_rgb(153, 209, 219),
260 sapphire: egui::Color32::from_rgb(133, 193, 220),
261 blue: egui::Color32::from_rgb(140, 170, 238),
262 lavender: egui::Color32::from_rgb(186, 187, 241),
263 text: egui::Color32::from_rgb(198, 208, 245),
264 subtext1: egui::Color32::from_rgb(181, 191, 226),
265 subtext0: egui::Color32::from_rgb(165, 173, 206),
266 overlay2: egui::Color32::from_rgb(148, 156, 187),
267 overlay1: egui::Color32::from_rgb(131, 139, 167),
268 overlay0: egui::Color32::from_rgb(115, 121, 148),
269 surface2: egui::Color32::from_rgb(98, 104, 128),
270 surface1: egui::Color32::from_rgb(81, 87, 109),
271 surface0: egui::Color32::from_rgb(65, 69, 89),
272 base: egui::Color32::from_rgb(48, 52, 70),
273 mantle: egui::Color32::from_rgb(41, 44, 60),
274 crust: egui::Color32::from_rgb(35, 38, 52),
275};
276
277pub const MACCHIATO: Theme = Theme {
278 rosewater: egui::Color32::from_rgb(244, 219, 214),
279 flamingo: egui::Color32::from_rgb(240, 198, 198),
280 pink: egui::Color32::from_rgb(245, 189, 230),
281 mauve: egui::Color32::from_rgb(198, 160, 246),
282 red: egui::Color32::from_rgb(237, 135, 150),
283 maroon: egui::Color32::from_rgb(238, 153, 160),
284 peach: egui::Color32::from_rgb(245, 169, 127),
285 yellow: egui::Color32::from_rgb(238, 212, 159),
286 green: egui::Color32::from_rgb(166, 218, 149),
287 teal: egui::Color32::from_rgb(139, 213, 202),
288 sky: egui::Color32::from_rgb(145, 215, 227),
289 sapphire: egui::Color32::from_rgb(125, 196, 228),
290 blue: egui::Color32::from_rgb(138, 173, 244),
291 lavender: egui::Color32::from_rgb(183, 189, 248),
292 text: egui::Color32::from_rgb(202, 211, 245),
293 subtext1: egui::Color32::from_rgb(184, 192, 224),
294 subtext0: egui::Color32::from_rgb(165, 173, 203),
295 overlay2: egui::Color32::from_rgb(147, 154, 183),
296 overlay1: egui::Color32::from_rgb(128, 135, 162),
297 overlay0: egui::Color32::from_rgb(110, 115, 141),
298 surface2: egui::Color32::from_rgb(91, 96, 120),
299 surface1: egui::Color32::from_rgb(73, 77, 100),
300 surface0: egui::Color32::from_rgb(54, 58, 79),
301 base: egui::Color32::from_rgb(36, 39, 58),
302 mantle: egui::Color32::from_rgb(30, 32, 48),
303 crust: egui::Color32::from_rgb(24, 25, 38),
304};
305
306pub const MOCHA: Theme = Theme {
307 rosewater: egui::Color32::from_rgb(245, 224, 220),
308 flamingo: egui::Color32::from_rgb(242, 205, 205),
309 pink: egui::Color32::from_rgb(245, 194, 231),
310 mauve: egui::Color32::from_rgb(203, 166, 247),
311 red: egui::Color32::from_rgb(243, 139, 168),
312 maroon: egui::Color32::from_rgb(235, 160, 172),
313 peach: egui::Color32::from_rgb(250, 179, 135),
314 yellow: egui::Color32::from_rgb(249, 226, 175),
315 green: egui::Color32::from_rgb(166, 227, 161),
316 teal: egui::Color32::from_rgb(148, 226, 213),
317 sky: egui::Color32::from_rgb(137, 220, 235),
318 sapphire: egui::Color32::from_rgb(116, 199, 236),
319 blue: egui::Color32::from_rgb(137, 180, 250),
320 lavender: egui::Color32::from_rgb(180, 190, 254),
321 text: egui::Color32::from_rgb(205, 214, 244),
322 subtext1: egui::Color32::from_rgb(186, 194, 222),
323 subtext0: egui::Color32::from_rgb(166, 173, 200),
324 overlay2: egui::Color32::from_rgb(147, 153, 178),
325 overlay1: egui::Color32::from_rgb(127, 132, 156),
326 overlay0: egui::Color32::from_rgb(108, 112, 134),
327 surface2: egui::Color32::from_rgb(88, 91, 112),
328 surface1: egui::Color32::from_rgb(69, 71, 90),
329 surface0: egui::Color32::from_rgb(49, 50, 68),
330 base: egui::Color32::from_rgb(30, 30, 46),
331 mantle: egui::Color32::from_rgb(24, 24, 37),
332 crust: egui::Color32::from_rgb(17, 17, 27),
333};