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 = (); 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 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}