alchemy_styles/
stylesheet.rs

1//! Implements a `StyleSheet`, which contains inner logic for
2//! determining what styles should be applied to a given widget.
3//!
4//! You can think of this as a compiled form of your CSS. You generally
5//! don't need to create these structs yourself, but feel free to if
6//! you have some creative use.
7
8use std::collections::HashMap;
9
10use crate::stretch::style::Style;
11use crate::styles::{Appearance, Dimension, Rect, Size, Styles};
12
13/// A `StyleSheet` contains selectors and parsed `Styles` attributes.
14/// It also has some logic to apply styles for n keys to a given `Style` node.
15#[derive(Debug)]
16pub struct StyleSheet(HashMap<&'static str, Vec<Styles>>);
17
18impl StyleSheet {
19    /// Creates a new `Stylesheet`.
20    pub fn new(styles: HashMap<&'static str, Vec<Styles>>) -> Self {
21        StyleSheet(styles)
22    }
23
24    pub fn apply_styles(&self, key: &str, style: &mut Style, appearance: &mut Appearance) {
25        match self.0.get(key) {
26            Some(styles) => { reduce_styles_into_style(styles, style, appearance); },
27            None => {}
28        }
29    }
30}
31
32/// This takes a list of styles, and a mutable style object, and attempts to configure the
33/// style object in a way that makes sense given n styles.
34fn reduce_styles_into_style(styles: &Vec<Styles>, layout: &mut Style, appearance: &mut Appearance) {
35    for style in styles { match style {
36        Styles::AlignContent(val) => { layout.align_content = *val; },
37        Styles::AlignItems(val) => { layout.align_items = *val; },
38        Styles::AlignSelf(val) => { layout.align_self = *val; },
39        Styles::AspectRatio(val) => { layout.aspect_ratio = *val; },
40        Styles::BackfaceVisibility(_val) => { },
41        Styles::BackgroundColor(val) => { appearance.background_color = *val; },
42
43        Styles::BorderColor(_val) => { },
44        Styles::BorderEndColor(_val) => { },
45        Styles::BorderBottomColor(_val) => { },
46        Styles::BorderLeftColor(_val) => { },
47        Styles::BorderRightColor(_val) => { },
48        Styles::BorderTopColor(_val) => { },
49        Styles::BorderStartColor(_val) => { },
50    
51        Styles::BorderStyle(_val) => { },
52        Styles::BorderEndStyle(_val) => { },
53        Styles::BorderBottomStyle(_val) => { },
54        Styles::BorderLeftStyle(_val) => { },
55        Styles::BorderRightStyle(_val) => { },
56        Styles::BorderTopStyle(_val) => { },
57        Styles::BorderStartStyle(_val) => { },
58    
59        Styles::BorderWidth(_val) => { },
60        Styles::BorderEndWidth(_val) => { },
61        Styles::BorderBottomWidth(_val) => { },
62        Styles::BorderLeftWidth(_val) => { },
63        Styles::BorderRightWidth(_val) => { },
64        Styles::BorderTopWidth(_val) => { },
65        Styles::BorderStartWidth(_val) => { },
66
67        Styles::BorderRadius(_val) => { },
68        Styles::BorderBottomEndRadius(_val) => { },
69        Styles::BorderBottomLeftRadius(_val) => { },
70        Styles::BorderBottomRightRadius(_val) => { },
71        Styles::BorderBottomStartRadius(_val) => { },
72        Styles::BorderTopLeftRadius(_val) => { },
73        Styles::BorderTopRightRadius(_val) => { },
74        Styles::BorderTopEndRadius(_val) => { },
75        Styles::BorderTopStartRadius(_val) => { },
76    
77        Styles::Bottom(val) => {
78            layout.position = Rect {
79                start: layout.position.start,
80                end: layout.position.end,
81                top: layout.position.top,
82                bottom: Dimension::Points(*val)
83            };
84        },
85
86        Styles::Direction(val) => { layout.direction = *val; },
87        Styles::Display(val) => { layout.display = *val; },
88        
89        Styles::End(val) => {
90            layout.position = Rect {
91                start: layout.position.start,
92                end: Dimension::Points(*val),
93                top: layout.position.top,
94                bottom: layout.position.bottom
95            };
96        },
97        
98        Styles::FlexBasis(val) => { layout.flex_basis = Dimension::Points(*val); },
99        Styles::FlexDirection(val) => { layout.flex_direction = *val; },
100        Styles::FlexGrow(val) => { layout.flex_grow = *val; },
101        Styles::FlexShrink(val) => { layout.flex_shrink = *val; },
102        Styles::FlexWrap(val) => { layout.flex_wrap = *val; },
103        
104        Styles::FontFamily(_val) => { },
105        Styles::FontLineHeight(_val) => { },
106        Styles::FontSize(val) => { appearance.font_size = *val; },
107        Styles::FontStyle(val) => { appearance.font_style = *val; },
108        Styles::FontWeight(val) => { appearance.font_weight = *val; },
109        
110        Styles::Height(val) => {
111            layout.size = Size {
112                width: layout.size.width,
113                height: Dimension::Points(*val)
114            };
115        },
116
117        Styles::JustifyContent(val) => { layout.justify_content = *val; },
118
119        Styles::Left(val) => {
120            layout.position = Rect {
121                start: Dimension::Points(*val),
122                end: layout.position.end,
123                top: layout.position.top,
124                bottom: layout.position.bottom
125            };
126        },
127
128        Styles::MarginBottom(val) => {
129            layout.margin = Rect {
130                start: layout.margin.start,
131                end: layout.margin.end,
132                top: layout.margin.top,
133                bottom: Dimension::Points(*val)
134            };
135        },
136
137        Styles::MarginEnd(val) => {
138            layout.margin = Rect {
139                start: layout.margin.start,
140                end: Dimension::Points(*val),
141                top: layout.margin.top,
142                bottom: layout.margin.bottom
143            };
144        },
145
146        Styles::MarginLeft(val) => {
147            layout.margin = Rect {
148                start: Dimension::Points(*val),
149                end: layout.margin.end,
150                top: layout.margin.top,
151                bottom: layout.margin.bottom
152            };
153        },
154
155        Styles::MarginRight(val) => {
156            layout.margin = Rect {
157                start: layout.margin.start,
158                end: Dimension::Points(*val),
159                top: layout.margin.top,
160                bottom: layout.margin.bottom
161            };
162        },
163        
164        Styles::MarginStart(val) => {
165            layout.margin = Rect {
166                start: Dimension::Points(*val),
167                end: layout.margin.end,
168                top: layout.margin.top,
169                bottom: layout.margin.bottom
170            };
171        },
172
173        Styles::MarginTop(val) => {
174            layout.margin = Rect {
175                start: layout.margin.start,
176                end: layout.margin.end,
177                top: Dimension::Points(*val),
178                bottom: layout.margin.bottom
179            };
180        },
181
182        Styles::MaxHeight(val) => {
183            layout.max_size = Size {
184                width: layout.max_size.width,
185                height: Dimension::Points(*val)
186            };
187        },
188
189        Styles::MaxWidth(val) => {
190            layout.max_size = Size {
191                width: Dimension::Points(*val),
192                height: layout.max_size.height
193            };
194        },
195
196        Styles::MinHeight(val) => {
197            layout.min_size = Size {
198                width: layout.min_size.width,
199                height: Dimension::Points(*val)
200            };
201        },
202
203        Styles::MinWidth(val) => {
204            layout.min_size = Size {
205                width: Dimension::Points(*val),
206                height: layout.min_size.height
207            };
208        },
209
210        Styles::Opacity(val) => { appearance.opacity = *val; },
211        Styles::Overflow(val) => { layout.overflow = *val; },
212
213        Styles::PaddingBottom(val) => {
214            layout.padding = Rect {
215                start: layout.padding.start,
216                end: layout.padding.end,
217                top: layout.padding.top,
218                bottom: Dimension::Points(*val)
219            };
220        },
221
222        Styles::PaddingEnd(val) => {
223            layout.padding = Rect {
224                start: layout.padding.start,
225                end: Dimension::Points(*val),
226                top: layout.padding.top,
227                bottom: layout.padding.bottom
228            };
229        },
230
231        Styles::PaddingLeft(val) => {
232            layout.padding = Rect {
233                start: Dimension::Points(*val),
234                end: layout.padding.end,
235                top: layout.padding.top,
236                bottom: layout.padding.bottom
237            };
238        },
239        
240        Styles::PaddingRight(val) => {
241            layout.padding = Rect {
242                start: layout.padding.start,
243                end: Dimension::Points(*val),
244                top: layout.padding.top,
245                bottom: layout.padding.bottom
246            };
247        },
248
249        Styles::PaddingStart(val) => {
250            layout.padding = Rect {
251                start: Dimension::Points(*val),
252                end: layout.padding.end,
253                top: layout.padding.top,
254                bottom: layout.padding.bottom
255            };
256        },
257
258        Styles::PaddingTop(val) => {
259            layout.padding = Rect {
260                start: layout.padding.start,
261                end: layout.padding.end,
262                top: Dimension::Points(*val),
263                bottom: layout.padding.bottom
264            };
265        },
266
267        Styles::PositionType(val) => { layout.position_type = *val; },
268
269        Styles::Right(val) => {
270            layout.position = Rect {
271                start: layout.position.start,
272                end: Dimension::Points(*val),
273                top: layout.position.top,
274                bottom: layout.position.bottom
275            };
276        },
277        
278        Styles::Start(val) => {
279            layout.position = Rect {
280                start: Dimension::Points(*val),
281                end: layout.position.end,
282                top: layout.position.top,
283                bottom: layout.position.bottom
284            };
285        },
286        
287        Styles::TextAlignment(val) => { appearance.text_alignment = *val; },
288        Styles::TextColor(val) => { appearance.text_color = *val; },
289        Styles::TextDecorationColor(val) => { appearance.text_decoration_color = *val; },
290        Styles::TextShadowColor(val) => { appearance.text_shadow_color = *val; },
291        Styles::TintColor(val) => { appearance.tint_color = *val; },
292        
293        Styles::Top(val) => {
294            layout.position = Rect {
295                start: layout.position.start,
296                end: layout.position.end,
297                top: Dimension::Points(*val),
298                bottom: layout.position.bottom
299            };
300        },
301        
302        Styles::Width(val) => {
303            layout.size = Size {
304                width: Dimension::Points(*val),
305                height: layout.size.height
306            };
307        }
308    }}
309}