maycoon_theme/
style.rs

1use indexmap::IndexMap;
2use peniko::{Brush, Color, Gradient};
3
4/// Styling map for defining widget appearance.
5#[derive(Clone, Debug)]
6pub struct Style {
7    map: IndexMap<String, StyleVal>,
8}
9
10impl Style {
11    /// Create a new empty style.
12    pub fn new() -> Self {
13        Self {
14            map: IndexMap::with_capacity(16),
15        }
16    }
17
18    /// Create a style from an array of strings and style values.
19    pub fn from_values(values: impl IntoIterator<Item = (String, StyleVal)>) -> Self {
20        Self {
21            map: IndexMap::from_iter(values),
22        }
23    }
24
25    /// Removes the style value from the map with the give name.
26    pub fn remove(&mut self, name: impl ToString) {
27        self.map.swap_remove(&name.to_string());
28    }
29
30    /// Insert a style value with the given name into the style map.
31    pub fn with_value(mut self, name: impl ToString, value: StyleVal) -> Self {
32        self.map.insert(name.to_string(), value);
33        self
34    }
35
36    /// Set a style value by name.
37    pub fn set(&mut self, name: impl ToString, value: StyleVal) {
38        self.map.insert(name.to_string(), value);
39    }
40
41    /// Set a color style value by name.
42    pub fn set_color(&mut self, name: impl ToString, color: Color) {
43        self.map.insert(name.to_string(), StyleVal::Color(color));
44    }
45
46    /// Set a gradient style value by name.
47    pub fn set_gradient(&mut self, name: impl ToString, gradient: Gradient) {
48        self.map
49            .insert(name.to_string(), StyleVal::Gradient(gradient));
50    }
51
52    /// Set a bool style value by name.
53    pub fn set_bool(&mut self, name: impl ToString, value: bool) {
54        self.map.insert(name.to_string(), StyleVal::Bool(value));
55    }
56
57    /// Set a brush style value by name.
58    pub fn set_brush(&mut self, name: impl ToString, brush: Brush) {
59        self.map.insert(name.to_string(), StyleVal::Brush(brush));
60    }
61
62    /// Set a float style value by name.
63    pub fn set_float(&mut self, name: impl ToString, value: f32) {
64        self.map.insert(name.to_string(), StyleVal::Float(value));
65    }
66
67    /// Set an int style value by name.
68    pub fn set_int(&mut self, name: impl ToString, value: i32) {
69        self.map.insert(name.to_string(), StyleVal::Int(value));
70    }
71
72    /// Set an unsized int style value by name.
73    pub fn set_uint(&mut self, name: impl ToString, value: u32) {
74        self.map.insert(name.to_string(), StyleVal::UInt(value));
75    }
76
77    /// Get a style value by name. Returns [None] if the value name does not exist.
78    pub fn get(&self, name: impl ToString) -> Option<StyleVal> {
79        self.map.get(&name.to_string()).cloned()
80    }
81
82    /// Get a color style value by name. Returns [None] if the value name does not exist.
83    pub fn get_color(&self, name: impl ToString) -> Option<Color> {
84        if let Some(val) = self.map.get(&name.to_string()) {
85            match val {
86                StyleVal::Color(color) => Some(*color),
87                _ => None,
88            }
89        } else {
90            None
91        }
92    }
93
94    /// Get a gradient style value by name. Returns [None] if the value name does not exist.
95    pub fn get_gradient(&self, name: impl ToString) -> Option<Gradient> {
96        if let Some(val) = self.map.get(&name.to_string()) {
97            match val {
98                StyleVal::Gradient(gradient) => Some(gradient.clone()),
99                _ => None,
100            }
101        } else {
102            None
103        }
104    }
105
106    /// Get a brush style value by name. Returns [None] if the value name does not exist.
107    pub fn get_brush(&self, name: impl ToString) -> Option<Brush> {
108        if let Some(val) = self.map.get(&name.to_string()) {
109            match val {
110                StyleVal::Brush(brush) => Some(brush.clone()),
111                _ => None,
112            }
113        } else {
114            None
115        }
116    }
117
118    /// Get a float style value by name. Returns [None] if the value name does not exist.
119    pub fn get_float(&self, name: impl ToString) -> Option<f32> {
120        if let Some(val) = self.map.get(&name.to_string()) {
121            match val {
122                StyleVal::Float(float) => Some(*float),
123                _ => None,
124            }
125        } else {
126            None
127        }
128    }
129
130    /// Get an int style value by name. Returns [None] if the value name does not exist.
131    pub fn get_int(&self, name: impl ToString) -> Option<i32> {
132        if let Some(val) = self.map.get(&name.to_string()) {
133            match val {
134                StyleVal::Int(int) => Some(*int),
135                _ => None,
136            }
137        } else {
138            None
139        }
140    }
141
142    /// Get an unsized int style value by name. Returns [None] if the value name does not exist.
143    pub fn get_uint(&self, name: impl ToString) -> Option<u32> {
144        if let Some(val) = self.map.get(&name.to_string()) {
145            match val {
146                StyleVal::UInt(uint) => Some(*uint),
147                _ => None,
148            }
149        } else {
150            None
151        }
152    }
153
154    /// Get a bool style value by name. Returns [None] if the value name does not exist.
155    pub fn get_bool(&self, name: impl ToString) -> Option<bool> {
156        if let Some(val) = self.map.get(&name.to_string()) {
157            match val {
158                StyleVal::Bool(bool) => Some(*bool),
159                _ => None,
160            }
161        } else {
162            None
163        }
164    }
165}
166
167impl Default for Style {
168    fn default() -> Self {
169        Self::new()
170    }
171}
172
173/// Default widget styles.
174#[derive(Clone, PartialEq, Debug)]
175pub struct DefaultStyles {
176    text: DefaultTextStyles,
177    container: DefaultContainerStyles,
178    interactive: DefaultInteractiveStyles,
179}
180
181impl DefaultStyles {
182    /// Create new default styles with given styles.
183    pub fn new(
184        text: DefaultTextStyles,
185        container: DefaultContainerStyles,
186        interactive: DefaultInteractiveStyles,
187    ) -> Self {
188        Self {
189            text,
190            container,
191            interactive,
192        }
193    }
194
195    /// Get the default styles for text widgets.
196    pub fn text(&self) -> &DefaultTextStyles {
197        &self.text
198    }
199
200    /// Get the default styles for container widgets.
201    pub fn container(&self) -> &DefaultContainerStyles {
202        &self.container
203    }
204
205    /// Get the default styles for interactive widgets.
206    pub fn interactive(&self) -> &DefaultInteractiveStyles {
207        &self.interactive
208    }
209}
210
211/// The default text widget styles.
212#[derive(Clone, PartialEq, Debug)]
213pub struct DefaultTextStyles {
214    foreground: Color,
215    background: Color,
216}
217
218impl DefaultTextStyles {
219    /// Create new default text styles with given colors.
220    pub fn new(foreground: Color, background: Color) -> Self {
221        Self {
222            foreground,
223            background,
224        }
225    }
226
227    /// Get the default foreground color.
228    pub fn foreground(&self) -> Color {
229        self.foreground
230    }
231
232    /// Get the default background color.
233    pub fn background(&self) -> Color {
234        self.background
235    }
236}
237
238/// The default container widget styles.
239#[derive(Clone, PartialEq, Debug)]
240pub struct DefaultContainerStyles {
241    foreground: Color,
242    background: Color,
243}
244
245impl DefaultContainerStyles {
246    /// Create new default container styles with given colors.
247    pub fn new(foreground: Color, background: Color) -> Self {
248        Self {
249            foreground,
250            background,
251        }
252    }
253
254    /// Get the default foreground color.
255    pub fn foreground(&self) -> Color {
256        self.foreground
257    }
258
259    /// Get the default background color.
260    pub fn background(&self) -> Color {
261        self.background
262    }
263}
264
265/// The default interactive widget styles.
266#[derive(Clone, PartialEq, Debug)]
267pub struct DefaultInteractiveStyles {
268    active: Color,
269    inactive: Color,
270    hover: Color,
271    disabled: Color,
272}
273
274impl DefaultInteractiveStyles {
275    /// Create new default interactive styles with given colors.
276    pub fn new(active: Color, inactive: Color, hover: Color, disabled: Color) -> Self {
277        Self {
278            active,
279            inactive,
280            hover,
281            disabled,
282        }
283    }
284
285    /// Get the default active widget color.
286    pub fn active(&self) -> Color {
287        self.active
288    }
289
290    /// Get the default inactive widget color.
291    pub fn inactive(&self) -> Color {
292        self.inactive
293    }
294
295    /// Get the default on-hover widget color.
296    pub fn hover(&self) -> Color {
297        self.hover
298    }
299
300    /// Get the default disabled widget color.
301    pub fn disabled(&self) -> Color {
302        self.disabled
303    }
304}
305
306/// A style value.
307#[derive(Clone, Debug)]
308pub enum StyleVal {
309    /// A color style value.
310    Color(Color),
311    /// A gradient style value.
312    Gradient(Gradient),
313    /// A brush style value.
314    Brush(Brush),
315    /// A float style value.
316    Float(f32),
317    /// An int style value.
318    Int(i32),
319    /// An unsized int style value.
320    UInt(u32),
321    /// A bool style value.
322    Bool(bool),
323}