system_theme/theme/
mod.rs1mod palette;
3
4use std::fmt::Debug;
5
6#[doc(inline)]
7pub use palette::ThemePalette;
8
9#[derive(Debug, Default, PartialEq, Clone, Copy)]
11pub enum ThemeScheme {
12 #[default]
14 Light,
15 Dark,
17}
18
19#[derive(Debug, Default, PartialEq, Clone, Copy)]
21pub enum ThemeContrast {
22 #[default]
24 Normal,
25 High,
27}
28
29#[derive(PartialEq, Clone, Copy)]
31pub struct ThemeColor {
32 pub red: f32,
34 pub green: f32,
36 pub blue: f32,
38}
39
40impl Debug for ThemeColor {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(
43 f,
44 "#{:02X}{:02X}{:02X}",
45 (self.red * 255.0) as u8,
46 (self.green * 255.0) as u8,
47 (self.blue * 255.0) as u8
48 )
49 }
50}
51
52impl ThemeColor {
53 pub const WHITE: Self = Self {
55 red: 1.0,
56 green: 1.0,
57 blue: 1.0,
58 };
59
60 pub const BLACK: Self = Self {
62 red: 0.0,
63 green: 0.0,
64 blue: 0.0,
65 };
66
67 pub const fn from_rgb8(red: u8, green: u8, blue: u8) -> Self {
69 Self {
70 red: red as f32 / 255.0,
71 green: green as f32 / 255.0,
72 blue: blue as f32 / 255.0,
73 }
74 }
75}
76
77#[derive(Debug, Default, PartialEq, Clone, Copy)]
79pub enum ThemeKind {
80 #[cfg_attr(target_os = "windows", default)]
82 Windows,
83 #[cfg_attr(target_os = "macos", default)]
85 MacOS,
86 #[cfg_attr(not(any(target_os = "windows", target_os = "macos")), default)]
88 Gtk,
89 Qt,
91}
92
93#[derive(Debug, Clone, PartialEq)]
95pub struct Theme {
96 pub name: String,
98 pub palette: ThemePalette,
100}
101
102impl Default for Theme {
103 fn default() -> Self {
104 Theme::new(
105 ThemeKind::default(),
106 ThemeScheme::default(),
107 ThemeContrast::default(),
108 None,
109 )
110 }
111}
112
113impl Theme {
114 pub fn new(
116 kind: ThemeKind,
117 scheme: ThemeScheme,
118 contrast: ThemeContrast,
119 accent: Option<ThemeColor>,
120 ) -> Self {
121 let (mut name, mut palette) = match kind {
122 ThemeKind::Windows => match scheme {
123 ThemeScheme::Light => ("FluentLight".to_string(), palette::FLUENT_LIGHT),
124 ThemeScheme::Dark => ("FluentDark".to_string(), palette::FLUENT_DARK),
125 },
126 ThemeKind::MacOS => match scheme {
127 ThemeScheme::Light => ("AquaLight".to_string(), palette::AQUA_LIGHT),
128 ThemeScheme::Dark => ("AquaDark".to_string(), palette::AQUA_DARK),
129 },
130 ThemeKind::Gtk => match scheme {
131 ThemeScheme::Light => ("AdwaitaLight".to_string(), palette::ADWAITA_LIGHT),
132 ThemeScheme::Dark => ("AdwaitaDark".to_string(), palette::ADWAITA_DARK),
133 },
134 ThemeKind::Qt => match scheme {
135 ThemeScheme::Light => ("BreezeLight".to_string(), palette::BREEZE_LIGHT),
136 ThemeScheme::Dark => ("BreezeDark".to_string(), palette::BREEZE_DARK),
137 },
138 };
139
140 if contrast == ThemeContrast::High {
142 name.push_str("HC");
144
145 match scheme {
146 ThemeScheme::Light => {
147 palette.background = ThemeColor::WHITE;
148 palette.foreground = ThemeColor::BLACK;
149 }
150 ThemeScheme::Dark => {
151 palette.background = ThemeColor::BLACK;
152 palette.foreground = ThemeColor::WHITE;
153 }
154 }
155 }
156
157 if let Some(accent) = accent {
159 palette.accent = accent;
160 }
161
162 Theme { name, palette }
163 }
164}