1use crate::logger;
2
3fn sanitize_positive(owner: &str, property: &str, value: f32) -> f32 {
4 if value <= 0.0 {
5 logger::warn(
6 "Layout",
7 &format!("{owner}.{property}() received {value}; ignoring."),
8 );
9 return 0.0;
10 }
11 value
12}
13
14#[derive(Clone, Copy, Debug, Default, PartialEq)]
15pub struct LabeledControlSizing {
16 indicator_size: f32,
17 label_font_size: f32,
18}
19
20impl LabeledControlSizing {
21 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn indicator_size(mut self, value: f32) -> Self {
26 self.indicator_size = sanitize_positive("LabeledControlSizing", "indicator_size", value);
27 self
28 }
29
30 pub fn label_font_size(mut self, value: f32) -> Self {
31 self.label_font_size = sanitize_positive("LabeledControlSizing", "label_font_size", value);
32 self
33 }
34
35 pub fn has_indicator_size(&self) -> bool {
36 self.indicator_size > 0.0
37 }
38
39 pub fn has_label_font_size(&self) -> bool {
40 self.label_font_size > 0.0
41 }
42
43 pub fn indicator_size_px(&self) -> f32 {
44 self.indicator_size
45 }
46
47 pub fn label_font_size_px(&self) -> f32 {
48 self.label_font_size
49 }
50}
51
52#[derive(Clone, Copy, Debug, Default, PartialEq)]
53pub struct SliderSizing {
54 thumb_size: f32,
55 track_thickness: f32,
56}
57
58impl SliderSizing {
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn thumb_size(mut self, value: f32) -> Self {
64 self.thumb_size = sanitize_positive("SliderSizing", "thumb_size", value);
65 self
66 }
67
68 pub fn track_thickness(mut self, value: f32) -> Self {
69 self.track_thickness = sanitize_positive("SliderSizing", "track_thickness", value);
70 self
71 }
72
73 pub fn has_thumb_size(&self) -> bool {
74 self.thumb_size > 0.0
75 }
76
77 pub fn has_track_thickness(&self) -> bool {
78 self.track_thickness > 0.0
79 }
80
81 pub fn thumb_size_px(&self) -> f32 {
82 self.thumb_size
83 }
84
85 pub fn track_thickness_px(&self) -> f32 {
86 self.track_thickness
87 }
88}
89
90#[derive(Clone, Copy, Debug, Default, PartialEq)]
91pub struct ProgressBarSizing {
92 length: f32,
93 thickness: f32,
94}
95
96impl ProgressBarSizing {
97 pub fn new() -> Self {
98 Self::default()
99 }
100
101 pub fn length(mut self, value: f32) -> Self {
102 self.length = sanitize_positive("ProgressBarSizing", "length", value);
103 self
104 }
105
106 pub fn thickness(mut self, value: f32) -> Self {
107 self.thickness = sanitize_positive("ProgressBarSizing", "thickness", value);
108 self
109 }
110
111 pub fn has_length(&self) -> bool {
112 self.length > 0.0
113 }
114
115 pub fn has_thickness(&self) -> bool {
116 self.thickness > 0.0
117 }
118
119 pub fn length_px(&self) -> f32 {
120 self.length
121 }
122
123 pub fn thickness_px(&self) -> f32 {
124 self.thickness
125 }
126}
127
128#[derive(Clone, Copy, Debug, Default, PartialEq)]
129pub struct DropdownSizing {
130 field_font_size: f32,
131 option_font_size: f32,
132 field_height: f32,
133 option_height: f32,
134 chevron_box_size: f32,
135 chevron_icon_size: f32,
136}
137
138impl DropdownSizing {
139 pub fn new() -> Self {
140 Self::default()
141 }
142
143 pub fn field_font_size(mut self, value: f32) -> Self {
144 self.field_font_size = sanitize_positive("DropdownSizing", "field_font_size", value);
145 self
146 }
147
148 pub fn option_font_size(mut self, value: f32) -> Self {
149 self.option_font_size = sanitize_positive("DropdownSizing", "option_font_size", value);
150 self
151 }
152
153 pub fn field_height(mut self, value: f32) -> Self {
154 self.field_height = sanitize_positive("DropdownSizing", "field_height", value);
155 self
156 }
157
158 pub fn option_height(mut self, value: f32) -> Self {
159 self.option_height = sanitize_positive("DropdownSizing", "option_height", value);
160 self
161 }
162
163 pub fn chevron_box_size(mut self, value: f32) -> Self {
164 self.chevron_box_size = sanitize_positive("DropdownSizing", "chevron_box_size", value);
165 self
166 }
167
168 pub fn chevron_icon_size(mut self, value: f32) -> Self {
169 self.chevron_icon_size = sanitize_positive("DropdownSizing", "chevron_icon_size", value);
170 self
171 }
172
173 pub fn has_field_font_size(&self) -> bool {
174 self.field_font_size > 0.0
175 }
176
177 pub fn has_option_font_size(&self) -> bool {
178 self.option_font_size > 0.0
179 }
180
181 pub fn has_field_height(&self) -> bool {
182 self.field_height > 0.0
183 }
184
185 pub fn has_option_height(&self) -> bool {
186 self.option_height > 0.0
187 }
188
189 pub fn has_chevron_box_size(&self) -> bool {
190 self.chevron_box_size > 0.0
191 }
192
193 pub fn has_chevron_icon_size(&self) -> bool {
194 self.chevron_icon_size > 0.0
195 }
196
197 pub fn field_font_size_px(&self) -> f32 {
198 self.field_font_size
199 }
200
201 pub fn option_font_size_px(&self) -> f32 {
202 self.option_font_size
203 }
204
205 pub fn field_height_px(&self) -> f32 {
206 self.field_height
207 }
208
209 pub fn option_height_px(&self) -> f32 {
210 self.option_height
211 }
212
213 pub fn chevron_box_size_px(&self) -> f32 {
214 self.chevron_box_size
215 }
216
217 pub fn chevron_icon_size_px(&self) -> f32 {
218 self.chevron_icon_size
219 }
220}
221
222#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
223pub struct ButtonColors {
224 pub(crate) background: Option<u32>,
225 pub(crate) background_hover: Option<u32>,
226 pub(crate) background_pressed: Option<u32>,
227 pub(crate) text_primary: Option<u32>,
228 pub(crate) text_muted: Option<u32>,
229 pub(crate) border: Option<u32>,
230}
231
232impl ButtonColors {
233 pub fn new() -> Self {
234 Self::default()
235 }
236
237 pub fn background(mut self, color: u32) -> Self {
238 self.background = Some(color);
239 self
240 }
241
242 pub fn background_hover(mut self, color: u32) -> Self {
243 self.background_hover = Some(color);
244 self
245 }
246
247 pub fn background_pressed(mut self, color: u32) -> Self {
248 self.background_pressed = Some(color);
249 self
250 }
251
252 pub fn text_primary(mut self, color: u32) -> Self {
253 self.text_primary = Some(color);
254 self
255 }
256
257 pub fn text_muted(mut self, color: u32) -> Self {
258 self.text_muted = Some(color);
259 self
260 }
261
262 pub fn border(mut self, color: u32) -> Self {
263 self.border = Some(color);
264 self
265 }
266
267 pub fn has_background(&self) -> bool {
268 self.background.is_some()
269 }
270
271 pub fn background_color(&self) -> u32 {
272 self.background.unwrap_or(0)
273 }
274
275 pub fn has_background_hover(&self) -> bool {
276 self.background_hover.is_some()
277 }
278
279 pub fn background_hover_color(&self) -> u32 {
280 self.background_hover.unwrap_or(0)
281 }
282
283 pub fn has_background_pressed(&self) -> bool {
284 self.background_pressed.is_some()
285 }
286
287 pub fn background_pressed_color(&self) -> u32 {
288 self.background_pressed.unwrap_or(0)
289 }
290
291 pub fn has_text_primary(&self) -> bool {
292 self.text_primary.is_some()
293 }
294
295 pub fn text_primary_color(&self) -> u32 {
296 self.text_primary.unwrap_or(0)
297 }
298
299 pub fn has_text_muted(&self) -> bool {
300 self.text_muted.is_some()
301 }
302
303 pub fn text_muted_color(&self) -> u32 {
304 self.text_muted.unwrap_or(0)
305 }
306
307 pub fn has_border(&self) -> bool {
308 self.border.is_some()
309 }
310
311 pub fn border_color(&self) -> u32 {
312 self.border.unwrap_or(0)
313 }
314}
315
316#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
317pub struct LabeledControlColors {
318 pub(crate) background: Option<u32>,
319 pub(crate) border: Option<u32>,
320 pub(crate) accent: Option<u32>,
321 pub(crate) text_primary: Option<u32>,
322 pub(crate) text_muted: Option<u32>,
323}
324
325impl LabeledControlColors {
326 pub fn new() -> Self {
327 Self::default()
328 }
329
330 pub fn background(mut self, color: u32) -> Self {
331 self.background = Some(color);
332 self
333 }
334
335 pub fn border(mut self, color: u32) -> Self {
336 self.border = Some(color);
337 self
338 }
339
340 pub fn accent(mut self, color: u32) -> Self {
341 self.accent = Some(color);
342 self
343 }
344
345 pub fn text_primary(mut self, color: u32) -> Self {
346 self.text_primary = Some(color);
347 self
348 }
349
350 pub fn text_muted(mut self, color: u32) -> Self {
351 self.text_muted = Some(color);
352 self
353 }
354
355 pub fn has_background(&self) -> bool {
356 self.background.is_some()
357 }
358
359 pub fn background_color(&self) -> u32 {
360 self.background.unwrap_or(0)
361 }
362
363 pub fn has_border(&self) -> bool {
364 self.border.is_some()
365 }
366
367 pub fn border_color(&self) -> u32 {
368 self.border.unwrap_or(0)
369 }
370
371 pub fn has_accent(&self) -> bool {
372 self.accent.is_some()
373 }
374
375 pub fn accent_color(&self) -> u32 {
376 self.accent.unwrap_or(0)
377 }
378
379 pub fn has_text_primary(&self) -> bool {
380 self.text_primary.is_some()
381 }
382
383 pub fn text_primary_color(&self) -> u32 {
384 self.text_primary.unwrap_or(0)
385 }
386
387 pub fn has_text_muted(&self) -> bool {
388 self.text_muted.is_some()
389 }
390
391 pub fn text_muted_color(&self) -> u32 {
392 self.text_muted.unwrap_or(0)
393 }
394}
395
396#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
397pub struct SliderColors {
398 pub(crate) track: Option<u32>,
399 pub(crate) fill: Option<u32>,
400 pub(crate) thumb: Option<u32>,
401}
402
403impl SliderColors {
404 pub fn new() -> Self {
405 Self::default()
406 }
407
408 pub fn track(mut self, color: u32) -> Self {
409 self.track = Some(color);
410 self
411 }
412
413 pub fn fill(mut self, color: u32) -> Self {
414 self.fill = Some(color);
415 self
416 }
417
418 pub fn thumb(mut self, color: u32) -> Self {
419 self.thumb = Some(color);
420 self
421 }
422
423 pub fn has_track(&self) -> bool {
424 self.track.is_some()
425 }
426
427 pub fn track_color(&self) -> u32 {
428 self.track.unwrap_or(0)
429 }
430
431 pub fn has_fill(&self) -> bool {
432 self.fill.is_some()
433 }
434
435 pub fn fill_color(&self) -> u32 {
436 self.fill.unwrap_or(0)
437 }
438
439 pub fn has_thumb(&self) -> bool {
440 self.thumb.is_some()
441 }
442
443 pub fn thumb_color(&self) -> u32 {
444 self.thumb.unwrap_or(0)
445 }
446}
447
448#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
449pub struct ProgressBarColors {
450 track: Option<u32>,
451 fill: Option<u32>,
452}
453
454impl ProgressBarColors {
455 pub fn new() -> Self {
456 Self::default()
457 }
458
459 pub fn track(mut self, color: u32) -> Self {
460 self.track = Some(color);
461 self
462 }
463
464 pub fn fill(mut self, color: u32) -> Self {
465 self.fill = Some(color);
466 self
467 }
468
469 pub fn has_track(&self) -> bool {
470 self.track.is_some()
471 }
472
473 pub fn track_color(&self) -> u32 {
474 self.track.unwrap_or(0)
475 }
476
477 pub fn has_fill(&self) -> bool {
478 self.fill.is_some()
479 }
480
481 pub fn fill_color(&self) -> u32 {
482 self.fill.unwrap_or(0)
483 }
484}
485
486#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
487pub struct DropdownColors {
488 pub(crate) background: Option<u32>,
489 pub(crate) text_primary: Option<u32>,
490 pub(crate) placeholder: Option<u32>,
491 pub(crate) border: Option<u32>,
492 pub(crate) accent: Option<u32>,
493}
494
495impl DropdownColors {
496 pub fn new() -> Self {
497 Self::default()
498 }
499
500 pub fn background(mut self, color: u32) -> Self {
501 self.background = Some(color);
502 self
503 }
504
505 pub fn text_primary(mut self, color: u32) -> Self {
506 self.text_primary = Some(color);
507 self
508 }
509
510 pub fn placeholder(mut self, color: u32) -> Self {
511 self.placeholder = Some(color);
512 self
513 }
514
515 pub fn border(mut self, color: u32) -> Self {
516 self.border = Some(color);
517 self
518 }
519
520 pub fn accent(mut self, color: u32) -> Self {
521 self.accent = Some(color);
522 self
523 }
524
525 pub fn has_background(&self) -> bool {
526 self.background.is_some()
527 }
528
529 pub fn background_color(&self) -> u32 {
530 self.background.unwrap_or(0)
531 }
532
533 pub fn has_text_primary(&self) -> bool {
534 self.text_primary.is_some()
535 }
536
537 pub fn text_primary_color(&self) -> u32 {
538 self.text_primary.unwrap_or(0)
539 }
540
541 pub fn has_placeholder(&self) -> bool {
542 self.placeholder.is_some()
543 }
544
545 pub fn placeholder_color(&self) -> u32 {
546 self.placeholder.unwrap_or(0)
547 }
548
549 pub fn has_border(&self) -> bool {
550 self.border.is_some()
551 }
552
553 pub fn border_color(&self) -> u32 {
554 self.border.unwrap_or(0)
555 }
556
557 pub fn has_accent(&self) -> bool {
558 self.accent.is_some()
559 }
560
561 pub fn accent_color(&self) -> u32 {
562 self.accent.unwrap_or(0)
563 }
564}
565
566#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
567pub struct TextInputColors {
568 pub(crate) background: Option<u32>,
569 pub(crate) text_primary: Option<u32>,
570 pub(crate) text_muted: Option<u32>,
571 pub(crate) placeholder: Option<u32>,
572 pub(crate) caret: Option<u32>,
573 pub(crate) border: Option<u32>,
574 pub(crate) accent: Option<u32>,
575}
576
577impl TextInputColors {
578 pub fn new() -> Self {
579 Self::default()
580 }
581
582 pub fn background(mut self, color: u32) -> Self {
583 self.background = Some(color);
584 self
585 }
586
587 pub fn text_primary(mut self, color: u32) -> Self {
588 self.text_primary = Some(color);
589 self
590 }
591
592 pub fn text_muted(mut self, color: u32) -> Self {
593 self.text_muted = Some(color);
594 self
595 }
596
597 pub fn placeholder(mut self, color: u32) -> Self {
598 self.placeholder = Some(color);
599 self
600 }
601
602 pub fn caret(mut self, color: u32) -> Self {
603 self.caret = Some(color);
604 self
605 }
606
607 pub fn border(mut self, color: u32) -> Self {
608 self.border = Some(color);
609 self
610 }
611
612 pub fn accent(mut self, color: u32) -> Self {
613 self.accent = Some(color);
614 self
615 }
616
617 pub fn has_background(&self) -> bool {
618 self.background.is_some()
619 }
620
621 pub fn background_color(&self) -> u32 {
622 self.background.unwrap_or(0)
623 }
624
625 pub fn has_text_primary(&self) -> bool {
626 self.text_primary.is_some()
627 }
628
629 pub fn text_primary_color(&self) -> u32 {
630 self.text_primary.unwrap_or(0)
631 }
632
633 pub fn has_text_muted(&self) -> bool {
634 self.text_muted.is_some()
635 }
636
637 pub fn text_muted_color(&self) -> u32 {
638 self.text_muted.unwrap_or(0)
639 }
640
641 pub fn has_placeholder(&self) -> bool {
642 self.placeholder.is_some()
643 }
644
645 pub fn placeholder_color(&self) -> u32 {
646 self.placeholder.unwrap_or(0)
647 }
648
649 pub fn has_caret(&self) -> bool {
650 self.caret.is_some()
651 }
652
653 pub fn caret_color(&self) -> u32 {
654 self.caret.unwrap_or(0)
655 }
656
657 pub fn has_border(&self) -> bool {
658 self.border.is_some()
659 }
660
661 pub fn border_color(&self) -> u32 {
662 self.border.unwrap_or(0)
663 }
664
665 pub fn has_accent(&self) -> bool {
666 self.accent.is_some()
667 }
668
669 pub fn accent_color(&self) -> u32 {
670 self.accent.unwrap_or(0)
671 }
672}