maycoon_theme/
style.rs

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