layoutcss_parser/components/
mod.rs

1use std::{collections::HashSet, hash::Hash, str::FromStr};
2
3use area::area_css;
4use center::center_css;
5use extender::extender_css;
6use grid::grid_css;
7use icon::icon_css;
8use row::row_css;
9use outsider::outsider_css;
10use r#box::box_css;
11use rack::rack_css;
12use sidebar::sidebar_css;
13use slider::slider_css;
14use stack::stack_css;
15use switcher::switcher_css;
16
17pub mod area;
18pub mod r#box;
19pub mod center;
20pub mod extender;
21pub mod grid;
22pub mod icon;
23pub mod row;
24pub mod outsider;
25pub mod rack;
26pub mod sidebar;
27pub mod slider;
28pub mod stack;
29pub mod switcher;
30
31#[derive(Debug, PartialEq, Eq, Hash, Clone)]
32pub enum Component<'a> {
33    Area {
34        template: Option<&'a str>,
35        rows: Vec<&'a str>,
36        cols: Vec<&'a str>,
37        gap: Option<&'a str>,
38        gap_x: Option<&'a str>,
39        gap_y: Option<&'a str>,
40    },
41    Box {
42        max_width: Option<&'a str>,
43        grow: bool,
44    },
45    Center {
46        max_width: Option<&'a str>,
47        and_text: bool,
48        recursive: bool,
49    },
50    Extender {
51        screen: bool,
52        keep_center: bool,
53        keep_p: bool,
54        keep_pl: bool,
55        keep_pr: bool,
56    },
57    Grid {
58        min_cell_width: Option<&'a str>,
59        min_cols: Option<&'a str>,
60        max_cols: Option<&'a str>,
61        gap: Option<&'a str>,
62        gap_x: Option<&'a str>,
63        gap_y: Option<&'a str>,
64    },
65    Icon {
66        scale: Option<&'a str>,
67        align: Option<&'a str>,
68        gap_dir: Option<&'a str>,
69        gap: Option<&'a str>,
70    },
71    Row {
72        nowrap: bool,
73        twin_width: bool,
74        direction: Option<&'a str>,
75        justify: Option<&'a str>,
76        align: Option<&'a str>,
77        gap: Option<&'a str>,
78        gap_x: Option<&'a str>,
79        gap_y: Option<&'a str>,
80    },
81    Outsider {
82        position: Option<&'a str>,
83        top: Option<&'a str>,
84        bottom: Option<&'a str>,
85        left: Option<&'a str>,
86        right: Option<&'a str>,
87    },
88    Rack {
89        height: Option<&'a str>,
90        min_height: Option<&'a str>,
91        max_height: Option<&'a str>,
92        gap: Option<&'a str>,
93    },
94    Sidebar {
95        reverse: bool,
96        shrink: bool,
97        side: Option<&'a str>,
98        side_width: Option<&'a str>,
99        content_min: Option<&'a str>,
100        gap: Option<&'a str>,
101        gap_x: Option<&'a str>,
102        gap_y: Option<&'a str>,
103    },
104    Slider {
105        hide_bar: bool,
106        item_width: Option<&'a str>,
107        height: Option<&'a str>,
108        gap: Option<&'a str>,
109    },
110    Stack {
111        gap: Option<&'a str>,
112        recursive: bool,
113    },
114    Switcher {
115        threshold: Option<&'a str>,
116        limit: Option<&'a str>,
117        reverse: bool,
118        gap: Option<&'a str>,
119        gap_x: Option<&'a str>,
120        gap_y: Option<&'a str>,
121    },
122}
123
124impl<'a> FromStr for Component<'a> {
125    type Err = (); // Use a static string for the error type.
126
127    fn from_str(s: &str) -> Result<Self, Self::Err> {
128        match s {
129            "area-l" => Ok(Self::Area {
130                template: None,
131                rows: vec![],
132                cols: vec![],
133                gap: None,
134                gap_x: None,
135                gap_y: None,
136            }),
137            "box-l" => Ok(Self::Box {
138                max_width: None,
139                grow: false,
140            }),
141            "center-l" => Ok(Self::Center {
142                max_width: None,
143                and_text: false,
144                recursive: false,
145            }),
146            "extender-l" => Ok(Self::Extender {
147                screen: false,
148                keep_center: false,
149                keep_p: false,
150                keep_pl: false,
151                keep_pr: false,
152            }),
153            "grid-l" => Ok(Self::Grid {
154                min_cell_width: None,
155                min_cols: None,
156                max_cols: None,
157                gap: None,
158                gap_x: None,
159                gap_y: None,
160            }),
161            "icon-l" => Ok(Self::Icon {
162                scale: None,
163                align: None,
164                gap_dir: None,
165                gap: None,
166            }),
167            "row-l" => Ok(Self::Row {
168                nowrap: false,
169                twin_width: false,
170                direction: None,
171                justify: None,
172                align: None,
173                gap: None,
174                gap_x: None,
175                gap_y: None,
176            }),
177            "outsider-l" => Ok(Self::Outsider {
178                position: None,
179                top: None,
180                bottom: None,
181                left: None,
182                right: None,
183            }),
184            "rack-l" => Ok(Self::Rack {
185                height: None,
186                min_height: None,
187                max_height: None,
188                gap: None,
189            }),
190            "sidebar-l" => Ok(Self::Sidebar {
191                reverse: false,
192                shrink: false,
193                side: None,
194                side_width: None,
195                content_min: None,
196                gap: None,
197                gap_x: None,
198                gap_y: None,
199            }),
200            "slider-l" => Ok(Self::Slider {
201                hide_bar: false,
202                item_width: None,
203                height: None,
204                gap: None,
205            }),
206            "stack-l" => Ok(Self::Stack {
207                gap: None,
208                recursive: false,
209            }),
210            "switcher-l" => Ok(Self::Switcher {
211                threshold: None,
212                limit: None,
213                reverse: false,
214                gap: None,
215                gap_x: None,
216                gap_y: None,
217            }),
218            _ => Err(()),
219        }
220    }
221}
222
223impl<'a> Component<'a> {
224    /// Insert the css of the component
225    /// inside the HashSet passed.
226    /// This method consumes the component, because we dont need it anymore
227    /// after we have inserted the css.
228    pub fn insert_css(self, harmonic_ratio: f64, set: &mut HashSet<String>) {
229        match self {
230            Component::Area {
231                template,
232                rows,
233                cols,
234                gap,
235                gap_x,
236                gap_y,
237            } => area_css(template, rows, cols, gap, gap_x, gap_y, harmonic_ratio, set),
238            Component::Box { max_width, grow } => box_css(max_width, grow, set),
239            Component::Center {
240                max_width,
241                and_text,
242                recursive,
243            } => center_css(max_width, and_text, recursive, set),
244            Component::Extender {
245                screen,
246                keep_center,
247                keep_p,
248                keep_pl,
249                keep_pr,
250            } => extender_css(screen, keep_center,keep_p, keep_pl, keep_pr,  set),
251            Component::Grid {
252                min_cell_width,
253                min_cols,
254                max_cols,
255                gap,
256                gap_x,
257                gap_y,
258            } => grid_css(
259                min_cell_width,
260                min_cols,
261                max_cols,
262                gap,
263                gap_x,
264                gap_y,
265                harmonic_ratio,
266                set,
267            ),
268            Component::Icon {
269                scale,
270                align,
271                gap_dir,
272                gap,
273            } => icon_css(scale, align, gap_dir, gap, harmonic_ratio, set),
274            Component::Row {
275                nowrap,
276                twin_width,
277                direction,
278                justify,
279                align,
280                gap,
281                gap_x,
282                gap_y,
283            } => row_css(
284                nowrap,
285                twin_width,
286                direction,
287                justify,
288                align,
289                gap,
290                gap_x,
291                gap_y,
292                harmonic_ratio,
293                set,
294            ),
295            Component::Outsider {
296                position,
297                top,
298                bottom,
299                left,
300                right,
301            } => outsider_css(position, top, bottom, left, right, harmonic_ratio, set),
302            Component::Rack {
303                height,
304                min_height,
305                max_height,
306                gap,
307            } => rack_css(height, min_height, max_height, gap, harmonic_ratio, set),
308            Component::Sidebar {
309                reverse,
310                shrink,
311                side,
312                side_width,
313                content_min,
314                gap,
315                gap_x,
316                gap_y,
317            } => sidebar_css(
318                reverse,
319                shrink,
320                side,
321                side_width,
322                content_min,
323                gap,
324                gap_x,
325                gap_y,
326                harmonic_ratio,
327                set,
328            ),
329            Component::Slider {
330                hide_bar,
331                item_width,
332                height,
333                gap,
334            } => slider_css(hide_bar, item_width, height, gap, harmonic_ratio, set),
335            Component::Stack { gap, recursive } => stack_css(gap, recursive, harmonic_ratio, set),
336            Component::Switcher {
337                threshold,
338                limit,
339                reverse,
340                gap,
341                gap_x,
342                gap_y,
343            } => switcher_css(
344                threshold,
345                limit,
346                reverse,
347                gap,
348                gap_x,
349                gap_y,
350                harmonic_ratio,
351                set,
352            ),
353        };
354    }
355}
356
357#[cfg(test)]
358mod tests {
359
360    use super::*;
361
362    #[test]
363    fn test_get_css_on_box() {
364        let mut set: HashSet<String> = HashSet::new();
365        let box_component = Component::Box {
366            max_width: Some("440px"),
367            grow: false,
368        };
369        box_component.insert_css(1.618, &mut set);
370        println!("{:?}", set);
371    }
372
373    #[test]
374    fn test_create_box() {
375        let box_component = Component::from_str("box-l");
376
377        assert_eq!(
378            box_component,
379            Ok(Component::Box {
380                max_width: None,
381                grow: false
382            })
383        );
384    }
385}