1use crate::error::ThemeResolutionError;
4use crate::model::border::{BorderSpec, ResolvedBorderSpec};
5
6const DEFAULT_FONT_DPI: f32 = 96.0;
12use crate::model::resolved::{
13 ResolvedIconSizes, ResolvedTextScale, ResolvedTextScaleEntry, ResolvedThemeDefaults,
14 ResolvedThemeVariant,
15};
16use crate::model::{FontSpec, ResolvedFontSpec, TextScaleEntry, ThemeVariant};
17
18fn require<T: Clone + Default>(field: &Option<T>, path: &str, missing: &mut Vec<String>) -> T {
26 match field {
27 Some(val) => val.clone(),
28 None => {
29 missing.push(path.to_string());
30 T::default()
31 }
32 }
33}
34
35fn require_font(
38 font: &FontSpec,
39 prefix: &str,
40 dpi: f32,
41 missing: &mut Vec<String>,
42) -> ResolvedFontSpec {
43 let family = require(&font.family, &format!("{prefix}.family"), missing);
44 let size = font.size.map(|fs| fs.to_px(dpi)).unwrap_or_else(|| {
45 missing.push(format!("{prefix}.size"));
46 0.0
47 });
48 let weight = require(&font.weight, &format!("{prefix}.weight"), missing);
49 let color = require(&font.color, &format!("{prefix}.color"), missing);
50 ResolvedFontSpec {
51 family,
52 size,
53 weight,
54 style: font.style.unwrap_or_default(),
55 color,
56 }
57}
58
59fn require_font_opt(
62 font: &Option<FontSpec>,
63 prefix: &str,
64 dpi: f32,
65 missing: &mut Vec<String>,
66) -> ResolvedFontSpec {
67 match font {
68 None => {
69 missing.push(prefix.to_string());
70 ResolvedFontSpec::default()
71 }
72 Some(f) => {
73 let family = require(&f.family, &format!("{prefix}.family"), missing);
74 let size = f.size.map(|fs| fs.to_px(dpi)).unwrap_or_else(|| {
75 missing.push(format!("{prefix}.size"));
76 0.0
77 });
78 let weight = require(&f.weight, &format!("{prefix}.weight"), missing);
79 let color = require(&f.color, &format!("{prefix}.color"), missing);
80 ResolvedFontSpec {
81 family,
82 size,
83 weight,
84 style: f.style.unwrap_or_default(),
85 color,
86 }
87 }
88 }
89}
90
91fn require_text_scale_entry(
95 entry: &Option<TextScaleEntry>,
96 prefix: &str,
97 dpi: f32,
98 missing: &mut Vec<String>,
99) -> ResolvedTextScaleEntry {
100 match entry {
101 None => {
102 missing.push(prefix.to_string());
103 ResolvedTextScaleEntry::default()
104 }
105 Some(e) => {
106 let size = e.size.map(|fs| fs.to_px(dpi)).unwrap_or_else(|| {
107 missing.push(format!("{prefix}.size"));
108 0.0
109 });
110 let line_height = e.line_height.map(|fs| fs.to_px(dpi)).unwrap_or_else(|| {
111 missing.push(format!("{prefix}.line_height"));
112 0.0
113 });
114 let weight = require(&e.weight, &format!("{prefix}.weight"), missing);
115 ResolvedTextScaleEntry {
116 size,
117 weight,
118 line_height,
119 }
120 }
121 }
122}
123
124fn require_border(
130 border: &Option<BorderSpec>,
131 prefix: &str,
132 missing: &mut Vec<String>,
133) -> ResolvedBorderSpec {
134 match border {
135 None => {
136 missing.push(prefix.to_string());
137 ResolvedBorderSpec::default()
138 }
139 Some(b) => {
140 let color = require(&b.color, &format!("{prefix}.color"), missing);
141 let corner_radius = require(
142 &b.corner_radius,
143 &format!("{prefix}.corner_radius"),
144 missing,
145 );
146 let line_width = require(&b.line_width, &format!("{prefix}.line_width"), missing);
147 let shadow_enabled = require(
148 &b.shadow_enabled,
149 &format!("{prefix}.shadow_enabled"),
150 missing,
151 );
152 ResolvedBorderSpec {
153 color,
154 corner_radius,
155 corner_radius_lg: b.corner_radius_lg.unwrap_or_default(),
156 line_width,
157 opacity: b.opacity.unwrap_or_default(),
158 shadow_enabled,
159 padding_horizontal: b.padding_horizontal.unwrap_or_default(),
160 padding_vertical: b.padding_vertical.unwrap_or_default(),
161 }
162 }
163 }
164}
165
166fn border_all_optional(border: &Option<BorderSpec>) -> ResolvedBorderSpec {
171 match border {
172 None => ResolvedBorderSpec::default(),
173 Some(b) => ResolvedBorderSpec {
174 color: b.color.unwrap_or_default(),
175 corner_radius: b.corner_radius.unwrap_or_default(),
176 corner_radius_lg: b.corner_radius_lg.unwrap_or_default(),
177 line_width: b.line_width.unwrap_or_default(),
178 opacity: b.opacity.unwrap_or_default(),
179 shadow_enabled: b.shadow_enabled.unwrap_or_default(),
180 padding_horizontal: b.padding_horizontal.unwrap_or_default(),
181 padding_vertical: b.padding_vertical.unwrap_or_default(),
182 },
183 }
184}
185
186fn require_border_partial(
189 border: &Option<BorderSpec>,
190 prefix: &str,
191 missing: &mut Vec<String>,
192) -> ResolvedBorderSpec {
193 match border {
194 None => {
195 missing.push(prefix.to_string());
196 ResolvedBorderSpec::default()
197 }
198 Some(b) => {
199 let color = require(&b.color, &format!("{prefix}.color"), missing);
200 let line_width = require(&b.line_width, &format!("{prefix}.line_width"), missing);
201 ResolvedBorderSpec {
202 color,
203 corner_radius: b.corner_radius.unwrap_or_default(),
204 corner_radius_lg: b.corner_radius_lg.unwrap_or_default(),
205 line_width,
206 opacity: b.opacity.unwrap_or_default(),
207 shadow_enabled: b.shadow_enabled.unwrap_or_default(),
208 padding_horizontal: b.padding_horizontal.unwrap_or_default(),
209 padding_vertical: b.padding_vertical.unwrap_or_default(),
210 }
211 }
212 }
213}
214
215fn check_non_negative(value: f32, path: &str, errors: &mut Vec<String>) {
223 if !value.is_finite() || value < 0.0 {
224 errors.push(format!(
225 "{path} must be a finite non-negative number, got {value}"
226 ));
227 }
228}
229
230fn check_positive(value: f32, path: &str, errors: &mut Vec<String>) {
232 if !value.is_finite() || value <= 0.0 {
233 errors.push(format!(
234 "{path} must be a finite positive number, got {value}"
235 ));
236 }
237}
238
239fn check_range_f32(value: f32, min: f32, max: f32, path: &str, errors: &mut Vec<String>) {
241 if !value.is_finite() || value < min || value > max {
242 errors.push(format!(
243 "{path} must be a finite number between {min} and {max}, got {value}"
244 ));
245 }
246}
247
248fn check_range_u16(value: u16, min: u16, max: u16, path: &str, errors: &mut Vec<String>) {
250 if value < min || value > max {
251 errors.push(format!("{path} must be {min}..={max}, got {value}"));
252 }
253}
254
255fn check_min_max(
257 min_val: f32,
258 max_val: f32,
259 min_name: &str,
260 max_name: &str,
261 errors: &mut Vec<String>,
262) {
263 if min_val > max_val {
264 errors.push(format!(
265 "{min_name} ({min_val}) must not exceed {max_name} ({max_val})"
266 ));
267 }
268}
269
270impl ThemeVariant {
271 #[must_use = "this returns the validation result; handle the Result or propagate with ?"]
288 pub fn validate(&self) -> crate::Result<ResolvedThemeVariant> {
289 let mut missing = Vec::new();
290
291 let dpi = self.defaults.font_dpi.unwrap_or(DEFAULT_FONT_DPI);
303
304 let defaults_font = require_font(&self.defaults.font, "defaults.font", dpi, &mut missing);
305 let defaults_line_height = require(
306 &self.defaults.line_height,
307 "defaults.line_height",
308 &mut missing,
309 );
310 let defaults_mono_font = require_font(
311 &self.defaults.mono_font,
312 "defaults.mono_font",
313 dpi,
314 &mut missing,
315 );
316
317 let defaults_background = require(
318 &self.defaults.background_color,
319 "defaults.background_color",
320 &mut missing,
321 );
322 let defaults_foreground = require(
323 &self.defaults.text_color,
324 "defaults.text_color",
325 &mut missing,
326 );
327 let defaults_accent = require(
328 &self.defaults.accent_color,
329 "defaults.accent_color",
330 &mut missing,
331 );
332 let defaults_accent_foreground = require(
333 &self.defaults.accent_text_color,
334 "defaults.accent_text_color",
335 &mut missing,
336 );
337 let defaults_surface = require(
338 &self.defaults.surface_color,
339 "defaults.surface_color",
340 &mut missing,
341 );
342 let defaults_border = require(
343 &self.defaults.border.color,
344 "defaults.border.color",
345 &mut missing,
346 );
347 let defaults_muted = require(
348 &self.defaults.muted_color,
349 "defaults.muted_color",
350 &mut missing,
351 );
352 let defaults_shadow = require(
353 &self.defaults.shadow_color,
354 "defaults.shadow_color",
355 &mut missing,
356 );
357 let defaults_link = require(
358 &self.defaults.link_color,
359 "defaults.link_color",
360 &mut missing,
361 );
362 let defaults_selection = require(
363 &self.defaults.selection_background,
364 "defaults.selection_background",
365 &mut missing,
366 );
367 let defaults_selection_foreground = require(
368 &self.defaults.selection_text_color,
369 "defaults.selection_text_color",
370 &mut missing,
371 );
372 let defaults_selection_inactive = require(
373 &self.defaults.selection_inactive_background,
374 "defaults.selection_inactive_background",
375 &mut missing,
376 );
377 let defaults_disabled_foreground = require(
378 &self.defaults.disabled_text_color,
379 "defaults.disabled_text_color",
380 &mut missing,
381 );
382
383 let defaults_danger = require(
384 &self.defaults.danger_color,
385 "defaults.danger_color",
386 &mut missing,
387 );
388 let defaults_danger_foreground = require(
389 &self.defaults.danger_text_color,
390 "defaults.danger_text_color",
391 &mut missing,
392 );
393 let defaults_warning = require(
394 &self.defaults.warning_color,
395 "defaults.warning_color",
396 &mut missing,
397 );
398 let defaults_warning_foreground = require(
399 &self.defaults.warning_text_color,
400 "defaults.warning_text_color",
401 &mut missing,
402 );
403 let defaults_success = require(
404 &self.defaults.success_color,
405 "defaults.success_color",
406 &mut missing,
407 );
408 let defaults_success_foreground = require(
409 &self.defaults.success_text_color,
410 "defaults.success_text_color",
411 &mut missing,
412 );
413 let defaults_info = require(
414 &self.defaults.info_color,
415 "defaults.info_color",
416 &mut missing,
417 );
418 let defaults_info_foreground = require(
419 &self.defaults.info_text_color,
420 "defaults.info_text_color",
421 &mut missing,
422 );
423
424 let defaults_radius = require(
425 &self.defaults.border.corner_radius,
426 "defaults.border.corner_radius",
427 &mut missing,
428 );
429 let defaults_radius_lg = require(
430 &self.defaults.border.corner_radius_lg,
431 "defaults.border.corner_radius_lg",
432 &mut missing,
433 );
434 let defaults_frame_width = require(
435 &self.defaults.border.line_width,
436 "defaults.border.line_width",
437 &mut missing,
438 );
439 let defaults_disabled_opacity = require(
440 &self.defaults.disabled_opacity,
441 "defaults.disabled_opacity",
442 &mut missing,
443 );
444 let defaults_border_opacity = require(
445 &self.defaults.border.opacity,
446 "defaults.border.opacity",
447 &mut missing,
448 );
449 let defaults_shadow_enabled = require(
450 &self.defaults.border.shadow_enabled,
451 "defaults.border.shadow_enabled",
452 &mut missing,
453 );
454
455 let defaults_focus_ring_color = require(
456 &self.defaults.focus_ring_color,
457 "defaults.focus_ring_color",
458 &mut missing,
459 );
460 let defaults_focus_ring_width = require(
461 &self.defaults.focus_ring_width,
462 "defaults.focus_ring_width",
463 &mut missing,
464 );
465 let defaults_focus_ring_offset = require(
466 &self.defaults.focus_ring_offset,
467 "defaults.focus_ring_offset",
468 &mut missing,
469 );
470
471 let defaults_border_padding_h = require(
472 &self.defaults.border.padding_horizontal,
473 "defaults.border.padding_horizontal",
474 &mut missing,
475 );
476 let defaults_border_padding_v = require(
477 &self.defaults.border.padding_vertical,
478 "defaults.border.padding_vertical",
479 &mut missing,
480 );
481 let defaults_text_selection_background = require(
482 &self.defaults.text_selection_background,
483 "defaults.text_selection_background",
484 &mut missing,
485 );
486 let defaults_text_selection_color = require(
487 &self.defaults.text_selection_color,
488 "defaults.text_selection_color",
489 &mut missing,
490 );
491
492 let defaults_icon_sizes_toolbar = require(
493 &self.defaults.icon_sizes.toolbar,
494 "defaults.icon_sizes.toolbar",
495 &mut missing,
496 );
497 let defaults_icon_sizes_small = require(
498 &self.defaults.icon_sizes.small,
499 "defaults.icon_sizes.small",
500 &mut missing,
501 );
502 let defaults_icon_sizes_large = require(
503 &self.defaults.icon_sizes.large,
504 "defaults.icon_sizes.large",
505 &mut missing,
506 );
507 let defaults_icon_sizes_dialog = require(
508 &self.defaults.icon_sizes.dialog,
509 "defaults.icon_sizes.dialog",
510 &mut missing,
511 );
512 let defaults_icon_sizes_panel = require(
513 &self.defaults.icon_sizes.panel,
514 "defaults.icon_sizes.panel",
515 &mut missing,
516 );
517
518 let defaults_font_dpi = dpi;
520
521 let defaults_text_scaling_factor = require(
522 &self.defaults.text_scaling_factor,
523 "defaults.text_scaling_factor",
524 &mut missing,
525 );
526 let defaults_reduce_motion = require(
527 &self.defaults.reduce_motion,
528 "defaults.reduce_motion",
529 &mut missing,
530 );
531 let defaults_high_contrast = require(
532 &self.defaults.high_contrast,
533 "defaults.high_contrast",
534 &mut missing,
535 );
536 let defaults_reduce_transparency = require(
537 &self.defaults.reduce_transparency,
538 "defaults.reduce_transparency",
539 &mut missing,
540 );
541
542 let ts_caption = require_text_scale_entry(
545 &self.text_scale.caption,
546 "text_scale.caption",
547 dpi,
548 &mut missing,
549 );
550 let ts_section_heading = require_text_scale_entry(
551 &self.text_scale.section_heading,
552 "text_scale.section_heading",
553 dpi,
554 &mut missing,
555 );
556 let ts_dialog_title = require_text_scale_entry(
557 &self.text_scale.dialog_title,
558 "text_scale.dialog_title",
559 dpi,
560 &mut missing,
561 );
562 let ts_display = require_text_scale_entry(
563 &self.text_scale.display,
564 "text_scale.display",
565 dpi,
566 &mut missing,
567 );
568
569 let window_background = require(
572 &self.window.background_color,
573 "window.background_color",
574 &mut missing,
575 );
576 let window_title_bar_background = require(
577 &self.window.title_bar_background,
578 "window.title_bar_background",
579 &mut missing,
580 );
581 let window_inactive_title_bar_background = require(
582 &self.window.inactive_title_bar_background,
583 "window.inactive_title_bar_background",
584 &mut missing,
585 );
586 let window_inactive_title_bar_foreground = require(
587 &self.window.inactive_title_bar_text_color,
588 "window.inactive_title_bar_text_color",
589 &mut missing,
590 );
591 let window_title_bar_font = require_font_opt(
592 &self.window.title_bar_font,
593 "window.title_bar_font",
594 dpi,
595 &mut missing,
596 );
597
598 let button_background = require(
601 &self.button.background_color,
602 "button.background_color",
603 &mut missing,
604 );
605 let button_primary_background = require(
606 &self.button.primary_background,
607 "button.primary_background",
608 &mut missing,
609 );
610 let button_primary_foreground = require(
611 &self.button.primary_text_color,
612 "button.primary_text_color",
613 &mut missing,
614 );
615 let button_min_width = require(&self.button.min_width, "button.min_width", &mut missing);
616 let button_min_height = require(&self.button.min_height, "button.min_height", &mut missing);
617 let button_icon_spacing = require(
618 &self.button.icon_text_gap,
619 "button.icon_text_gap",
620 &mut missing,
621 );
622 let button_disabled_opacity = require(
623 &self.button.disabled_opacity,
624 "button.disabled_opacity",
625 &mut missing,
626 );
627 let button_font = require_font_opt(&self.button.font, "button.font", dpi, &mut missing);
628
629 let input_background = require(
632 &self.input.background_color,
633 "input.background_color",
634 &mut missing,
635 );
636 let input_placeholder = require(
637 &self.input.placeholder_color,
638 "input.placeholder_color",
639 &mut missing,
640 );
641 let input_caret = require(&self.input.caret_color, "input.caret_color", &mut missing);
642 let input_selection = require(
643 &self.input.selection_background,
644 "input.selection_background",
645 &mut missing,
646 );
647 let input_selection_foreground = require(
648 &self.input.selection_text_color,
649 "input.selection_text_color",
650 &mut missing,
651 );
652 let input_min_height = require(&self.input.min_height, "input.min_height", &mut missing);
653 let input_font = require_font_opt(&self.input.font, "input.font", dpi, &mut missing);
654
655 let checkbox_checked_background = require(
658 &self.checkbox.checked_background,
659 "checkbox.checked_background",
660 &mut missing,
661 );
662 let checkbox_indicator_size = require(
663 &self.checkbox.indicator_width,
664 "checkbox.indicator_width",
665 &mut missing,
666 );
667 let checkbox_spacing =
668 require(&self.checkbox.label_gap, "checkbox.label_gap", &mut missing);
669
670 let menu_background = require(
673 &self.menu.background_color,
674 "menu.background_color",
675 &mut missing,
676 );
677 let menu_separator = require(
678 &self.menu.separator_color,
679 "menu.separator_color",
680 &mut missing,
681 );
682 let menu_item_height = require(&self.menu.row_height, "menu.row_height", &mut missing);
683 let menu_icon_spacing =
684 require(&self.menu.icon_text_gap, "menu.icon_text_gap", &mut missing);
685 let menu_font = require_font_opt(&self.menu.font, "menu.font", dpi, &mut missing);
686
687 let tooltip_background = require(
690 &self.tooltip.background_color,
691 "tooltip.background_color",
692 &mut missing,
693 );
694 let tooltip_max_width = require(&self.tooltip.max_width, "tooltip.max_width", &mut missing);
695 let tooltip_font = require_font_opt(&self.tooltip.font, "tooltip.font", dpi, &mut missing);
696
697 let scrollbar_track = require(
700 &self.scrollbar.track_color,
701 "scrollbar.track_color",
702 &mut missing,
703 );
704 let scrollbar_thumb = require(
705 &self.scrollbar.thumb_color,
706 "scrollbar.thumb_color",
707 &mut missing,
708 );
709 let scrollbar_thumb_hover = require(
710 &self.scrollbar.thumb_hover_color,
711 "scrollbar.thumb_hover_color",
712 &mut missing,
713 );
714 let scrollbar_width = require(
715 &self.scrollbar.groove_width,
716 "scrollbar.groove_width",
717 &mut missing,
718 );
719 let scrollbar_min_thumb_height = require(
720 &self.scrollbar.min_thumb_length,
721 "scrollbar.min_thumb_length",
722 &mut missing,
723 );
724 let scrollbar_slider_width = require(
725 &self.scrollbar.thumb_width,
726 "scrollbar.thumb_width",
727 &mut missing,
728 );
729 let scrollbar_overlay_mode = require(
730 &self.scrollbar.overlay_mode,
731 "scrollbar.overlay_mode",
732 &mut missing,
733 );
734
735 let slider_fill = require(&self.slider.fill_color, "slider.fill_color", &mut missing);
738 let slider_track = require(&self.slider.track_color, "slider.track_color", &mut missing);
739 let slider_thumb = require(&self.slider.thumb_color, "slider.thumb_color", &mut missing);
740 let slider_track_height = require(
741 &self.slider.track_height,
742 "slider.track_height",
743 &mut missing,
744 );
745 let slider_thumb_size = require(
746 &self.slider.thumb_diameter,
747 "slider.thumb_diameter",
748 &mut missing,
749 );
750 let slider_tick_length = require(
751 &self.slider.tick_mark_length,
752 "slider.tick_mark_length",
753 &mut missing,
754 );
755
756 let progress_bar_fill = require(
759 &self.progress_bar.fill_color,
760 "progress_bar.fill_color",
761 &mut missing,
762 );
763 let progress_bar_track = require(
764 &self.progress_bar.track_color,
765 "progress_bar.track_color",
766 &mut missing,
767 );
768 let progress_bar_height = require(
769 &self.progress_bar.track_height,
770 "progress_bar.track_height",
771 &mut missing,
772 );
773 let progress_bar_min_width = require(
774 &self.progress_bar.min_width,
775 "progress_bar.min_width",
776 &mut missing,
777 );
778 let tab_background = require(
783 &self.tab.background_color,
784 "tab.background_color",
785 &mut missing,
786 );
787 let tab_active_background = require(
788 &self.tab.active_background,
789 "tab.active_background",
790 &mut missing,
791 );
792 let tab_active_foreground = require(
793 &self.tab.active_text_color,
794 "tab.active_text_color",
795 &mut missing,
796 );
797 let tab_bar_background =
798 require(&self.tab.bar_background, "tab.bar_background", &mut missing);
799 let tab_min_width = require(&self.tab.min_width, "tab.min_width", &mut missing);
800 let tab_min_height = require(&self.tab.min_height, "tab.min_height", &mut missing);
801 let tab_hover_text_color = require(
802 &self.tab.hover_text_color,
803 "tab.hover_text_color",
804 &mut missing,
805 );
806
807 let sidebar_background = require(
810 &self.sidebar.background_color,
811 "sidebar.background_color",
812 &mut missing,
813 );
814
815 let toolbar_height = require(&self.toolbar.bar_height, "toolbar.bar_height", &mut missing);
818 let toolbar_item_spacing =
819 require(&self.toolbar.item_gap, "toolbar.item_gap", &mut missing);
820 let toolbar_font = require_font_opt(&self.toolbar.font, "toolbar.font", dpi, &mut missing);
821
822 let status_bar_font =
825 require_font_opt(&self.status_bar.font, "status_bar.font", dpi, &mut missing);
826
827 let list_background = require(
830 &self.list.background_color,
831 "list.background_color",
832 &mut missing,
833 );
834 let list_alternate_row = require(
835 &self.list.alternate_row_background,
836 "list.alternate_row_background",
837 &mut missing,
838 );
839 let list_selection = require(
840 &self.list.selection_background,
841 "list.selection_background",
842 &mut missing,
843 );
844 let list_selection_foreground = require(
845 &self.list.selection_text_color,
846 "list.selection_text_color",
847 &mut missing,
848 );
849 let list_header_background = require(
850 &self.list.header_background,
851 "list.header_background",
852 &mut missing,
853 );
854 let list_grid_color = require(&self.list.grid_color, "list.grid_color", &mut missing);
855 let list_item_height = require(&self.list.row_height, "list.row_height", &mut missing);
856
857 let popover_background = require(
860 &self.popover.background_color,
861 "popover.background_color",
862 &mut missing,
863 );
864
865 let splitter_width = require(
868 &self.splitter.divider_width,
869 "splitter.divider_width",
870 &mut missing,
871 );
872
873 let separator_color = require(
876 &self.separator.line_color,
877 "separator.line_color",
878 &mut missing,
879 );
880
881 let switch_checked_background = require(
884 &self.switch.checked_background,
885 "switch.checked_background",
886 &mut missing,
887 );
888 let switch_unchecked_background = require(
889 &self.switch.unchecked_background,
890 "switch.unchecked_background",
891 &mut missing,
892 );
893 let switch_thumb_background = require(
894 &self.switch.thumb_background,
895 "switch.thumb_background",
896 &mut missing,
897 );
898 let switch_track_width =
899 require(&self.switch.track_width, "switch.track_width", &mut missing);
900 let switch_track_height = require(
901 &self.switch.track_height,
902 "switch.track_height",
903 &mut missing,
904 );
905 let switch_thumb_size = require(
906 &self.switch.thumb_diameter,
907 "switch.thumb_diameter",
908 &mut missing,
909 );
910 let switch_track_radius = require(
911 &self.switch.track_radius,
912 "switch.track_radius",
913 &mut missing,
914 );
915
916 let dialog_min_width = require(&self.dialog.min_width, "dialog.min_width", &mut missing);
919 let dialog_max_width = require(&self.dialog.max_width, "dialog.max_width", &mut missing);
920 let dialog_min_height = require(&self.dialog.min_height, "dialog.min_height", &mut missing);
921 let dialog_max_height = require(&self.dialog.max_height, "dialog.max_height", &mut missing);
922 let dialog_button_spacing =
923 require(&self.dialog.button_gap, "dialog.button_gap", &mut missing);
924 let dialog_icon_size = require(&self.dialog.icon_size, "dialog.icon_size", &mut missing);
925 let dialog_button_order = require(
926 &self.dialog.button_order,
927 "dialog.button_order",
928 &mut missing,
929 );
930 let dialog_title_font = require_font_opt(
931 &self.dialog.title_font,
932 "dialog.title_font",
933 dpi,
934 &mut missing,
935 );
936
937 let spinner_fill = require(&self.spinner.fill_color, "spinner.fill_color", &mut missing);
940 let spinner_diameter = require(&self.spinner.diameter, "spinner.diameter", &mut missing);
941 let spinner_min_size = require(
942 &self.spinner.min_diameter,
943 "spinner.min_diameter",
944 &mut missing,
945 );
946 let spinner_stroke_width = require(
947 &self.spinner.stroke_width,
948 "spinner.stroke_width",
949 &mut missing,
950 );
951
952 let combo_box_min_height = require(
955 &self.combo_box.min_height,
956 "combo_box.min_height",
957 &mut missing,
958 );
959 let combo_box_min_width = require(
960 &self.combo_box.min_width,
961 "combo_box.min_width",
962 &mut missing,
963 );
964 let combo_box_arrow_size = require(
965 &self.combo_box.arrow_icon_size,
966 "combo_box.arrow_icon_size",
967 &mut missing,
968 );
969 let combo_box_arrow_area_width = require(
970 &self.combo_box.arrow_area_width,
971 "combo_box.arrow_area_width",
972 &mut missing,
973 );
974
975 let segmented_control_segment_height = require(
978 &self.segmented_control.segment_height,
979 "segmented_control.segment_height",
980 &mut missing,
981 );
982 let segmented_control_separator_width = require(
983 &self.segmented_control.separator_width,
984 "segmented_control.separator_width",
985 &mut missing,
986 );
987
988 let card_background = require(
991 &self.card.background_color,
992 "card.background_color",
993 &mut missing,
994 );
995
996 let expander_header_height = require(
999 &self.expander.header_height,
1000 "expander.header_height",
1001 &mut missing,
1002 );
1003 let expander_arrow_size = require(
1004 &self.expander.arrow_icon_size,
1005 "expander.arrow_icon_size",
1006 &mut missing,
1007 );
1008
1009 let link_visited = require(
1012 &self.link.visited_text_color,
1013 "link.visited_text_color",
1014 &mut missing,
1015 );
1016 let link_background = require(
1017 &self.link.background_color,
1018 "link.background_color",
1019 &mut missing,
1020 );
1021 let link_hover_bg = require(
1022 &self.link.hover_background,
1023 "link.hover_background",
1024 &mut missing,
1025 );
1026 let link_underline = require(&self.link.underline_enabled, "link.underline", &mut missing);
1027
1028 let icon_set = require(&self.icon_set, "icon_set", &mut missing);
1031 let icon_theme = require(&self.icon_theme, "icon_theme", &mut missing);
1032
1033 let window_border_spec = require_border(&self.window.border, "window.border", &mut missing);
1037
1038 let button_hover_background = require(
1040 &self.button.hover_background,
1041 "button.hover_background",
1042 &mut missing,
1043 );
1044 let button_hover_text_color = require(
1045 &self.button.hover_text_color,
1046 "button.hover_text_color",
1047 &mut missing,
1048 );
1049 let button_border_spec = require_border(&self.button.border, "button.border", &mut missing);
1050 let button_active_text_color = require(
1051 &self.button.active_text_color,
1052 "button.active_text_color",
1053 &mut missing,
1054 );
1055 let button_disabled_text_color = require(
1056 &self.button.disabled_text_color,
1057 "button.disabled_text_color",
1058 &mut missing,
1059 );
1060
1061 let input_disabled_opacity = require(
1063 &self.input.disabled_opacity,
1064 "input.disabled_opacity",
1065 &mut missing,
1066 );
1067 let input_border_spec = require_border(&self.input.border, "input.border", &mut missing);
1068 let input_disabled_text_color = require(
1069 &self.input.disabled_text_color,
1070 "input.disabled_text_color",
1071 &mut missing,
1072 );
1073
1074 let checkbox_background_color = require(
1076 &self.checkbox.background_color,
1077 "checkbox.background_color",
1078 &mut missing,
1079 );
1080 let checkbox_indicator_color = require(
1081 &self.checkbox.indicator_color,
1082 "checkbox.indicator_color",
1083 &mut missing,
1084 );
1085 let checkbox_disabled_opacity = require(
1086 &self.checkbox.disabled_opacity,
1087 "checkbox.disabled_opacity",
1088 &mut missing,
1089 );
1090 let checkbox_font =
1091 require_font_opt(&self.checkbox.font, "checkbox.font", dpi, &mut missing);
1092 let checkbox_border_spec =
1093 require_border(&self.checkbox.border, "checkbox.border", &mut missing);
1094 let checkbox_disabled_text_color = require(
1095 &self.checkbox.disabled_text_color,
1096 "checkbox.disabled_text_color",
1097 &mut missing,
1098 );
1099
1100 let menu_icon_size = require(&self.menu.icon_size, "menu.icon_size", &mut missing);
1102 let menu_hover_background = require(
1103 &self.menu.hover_background,
1104 "menu.hover_background",
1105 &mut missing,
1106 );
1107 let menu_hover_text_color = require(
1108 &self.menu.hover_text_color,
1109 "menu.hover_text_color",
1110 &mut missing,
1111 );
1112 let menu_disabled_text_color = require(
1113 &self.menu.disabled_text_color,
1114 "menu.disabled_text_color",
1115 &mut missing,
1116 );
1117 let menu_border_spec = border_all_optional(&self.menu.border);
1119
1120 let tooltip_border_spec =
1122 require_border(&self.tooltip.border, "tooltip.border", &mut missing);
1123
1124 let slider_disabled_opacity = require(
1126 &self.slider.disabled_opacity,
1127 "slider.disabled_opacity",
1128 &mut missing,
1129 );
1130
1131 let progress_bar_border_spec = require_border(
1133 &self.progress_bar.border,
1134 "progress_bar.border",
1135 &mut missing,
1136 );
1137
1138 let tab_font = require_font_opt(&self.tab.font, "tab.font", dpi, &mut missing);
1140 let tab_border_spec = border_all_optional(&self.tab.border);
1142
1143 let sidebar_selection_background = require(
1145 &self.sidebar.selection_background,
1146 "sidebar.selection_background",
1147 &mut missing,
1148 );
1149 let sidebar_selection_text_color = require(
1150 &self.sidebar.selection_text_color,
1151 "sidebar.selection_text_color",
1152 &mut missing,
1153 );
1154 let sidebar_hover_background = require(
1155 &self.sidebar.hover_background,
1156 "sidebar.hover_background",
1157 &mut missing,
1158 );
1159 let sidebar_font = require_font_opt(&self.sidebar.font, "sidebar.font", dpi, &mut missing);
1160 let sidebar_border_spec =
1161 require_border_partial(&self.sidebar.border, "sidebar.border", &mut missing);
1162
1163 let toolbar_background_color = require(
1165 &self.toolbar.background_color,
1166 "toolbar.background_color",
1167 &mut missing,
1168 );
1169 let toolbar_icon_size = require(&self.toolbar.icon_size, "toolbar.icon_size", &mut missing);
1170 let toolbar_border_spec =
1171 require_border(&self.toolbar.border, "toolbar.border", &mut missing);
1172
1173 let status_bar_background_color = require(
1175 &self.status_bar.background_color,
1176 "status_bar.background_color",
1177 &mut missing,
1178 );
1179 let status_bar_border_spec =
1180 require_border_partial(&self.status_bar.border, "status_bar.border", &mut missing);
1181
1182 let list_item_font =
1184 require_font_opt(&self.list.item_font, "list.item_font", dpi, &mut missing);
1185 let list_header_font = require_font_opt(
1186 &self.list.header_font,
1187 "list.header_font",
1188 dpi,
1189 &mut missing,
1190 );
1191 let list_hover_background = require(
1192 &self.list.hover_background,
1193 "list.hover_background",
1194 &mut missing,
1195 );
1196 let list_hover_text_color = require(
1197 &self.list.hover_text_color,
1198 "list.hover_text_color",
1199 &mut missing,
1200 );
1201 let list_disabled_text_color = require(
1202 &self.list.disabled_text_color,
1203 "list.disabled_text_color",
1204 &mut missing,
1205 );
1206 let list_border_spec = require_border(&self.list.border, "list.border", &mut missing);
1207
1208 let popover_font = require_font_opt(&self.popover.font, "popover.font", dpi, &mut missing);
1210 let popover_border_spec =
1211 require_border(&self.popover.border, "popover.border", &mut missing);
1212
1213 let splitter_divider_color = require(
1215 &self.splitter.divider_color,
1216 "splitter.divider_color",
1217 &mut missing,
1218 );
1219 let splitter_hover_color = require(
1220 &self.splitter.hover_color,
1221 "splitter.hover_color",
1222 &mut missing,
1223 );
1224
1225 let separator_line_width = require(
1227 &self.separator.line_width,
1228 "separator.line_width",
1229 &mut missing,
1230 );
1231
1232 let switch_disabled_opacity = require(
1234 &self.switch.disabled_opacity,
1235 "switch.disabled_opacity",
1236 &mut missing,
1237 );
1238
1239 let dialog_background_color = require(
1241 &self.dialog.background_color,
1242 "dialog.background_color",
1243 &mut missing,
1244 );
1245 let dialog_body_font = require_font_opt(
1246 &self.dialog.body_font,
1247 "dialog.body_font",
1248 dpi,
1249 &mut missing,
1250 );
1251 let dialog_border_spec = require_border(&self.dialog.border, "dialog.border", &mut missing);
1252
1253 let link_font = require_font_opt(&self.link.font, "link.font", dpi, &mut missing);
1255 let link_hover_text_color = require(
1256 &self.link.hover_text_color,
1257 "link.hover_text_color",
1258 &mut missing,
1259 );
1260 let link_active_text_color = require(
1261 &self.link.active_text_color,
1262 "link.active_text_color",
1263 &mut missing,
1264 );
1265 let link_disabled_text_color = require(
1266 &self.link.disabled_text_color,
1267 "link.disabled_text_color",
1268 &mut missing,
1269 );
1270
1271 let combo_box_background_color = require(
1273 &self.combo_box.background_color,
1274 "combo_box.background_color",
1275 &mut missing,
1276 );
1277 let combo_box_disabled_opacity = require(
1278 &self.combo_box.disabled_opacity,
1279 "combo_box.disabled_opacity",
1280 &mut missing,
1281 );
1282 let combo_box_disabled_text_color = require(
1283 &self.combo_box.disabled_text_color,
1284 "combo_box.disabled_text_color",
1285 &mut missing,
1286 );
1287 let combo_box_font =
1288 require_font_opt(&self.combo_box.font, "combo_box.font", dpi, &mut missing);
1289 let combo_box_border_spec =
1290 require_border(&self.combo_box.border, "combo_box.border", &mut missing);
1291
1292 let segmented_control_background_color = require(
1294 &self.segmented_control.background_color,
1295 "segmented_control.background_color",
1296 &mut missing,
1297 );
1298 let segmented_control_active_background = require(
1299 &self.segmented_control.active_background,
1300 "segmented_control.active_background",
1301 &mut missing,
1302 );
1303 let segmented_control_active_text_color = require(
1304 &self.segmented_control.active_text_color,
1305 "segmented_control.active_text_color",
1306 &mut missing,
1307 );
1308 let segmented_control_disabled_opacity = require(
1309 &self.segmented_control.disabled_opacity,
1310 "segmented_control.disabled_opacity",
1311 &mut missing,
1312 );
1313 let segmented_control_font = require_font_opt(
1314 &self.segmented_control.font,
1315 "segmented_control.font",
1316 dpi,
1317 &mut missing,
1318 );
1319 let segmented_control_border_spec = require_border(
1320 &self.segmented_control.border,
1321 "segmented_control.border",
1322 &mut missing,
1323 );
1324
1325 let card_border_spec = border_all_optional(&self.card.border);
1327
1328 let expander_font =
1330 require_font_opt(&self.expander.font, "expander.font", dpi, &mut missing);
1331 let expander_border_spec =
1332 require_border(&self.expander.border, "expander.border", &mut missing);
1333
1334 check_positive(defaults_font.size, "defaults.font.size", &mut missing);
1346 check_range_u16(
1347 defaults_font.weight,
1348 100,
1349 900,
1350 "defaults.font.weight",
1351 &mut missing,
1352 );
1353 check_positive(
1354 defaults_mono_font.size,
1355 "defaults.mono_font.size",
1356 &mut missing,
1357 );
1358 check_range_u16(
1359 defaults_mono_font.weight,
1360 100,
1361 900,
1362 "defaults.mono_font.weight",
1363 &mut missing,
1364 );
1365
1366 check_positive(defaults_line_height, "defaults.line_height", &mut missing);
1368 check_positive(
1369 defaults_text_scaling_factor,
1370 "defaults.text_scaling_factor",
1371 &mut missing,
1372 );
1373
1374 check_non_negative(
1376 defaults_radius,
1377 "defaults.border.corner_radius",
1378 &mut missing,
1379 );
1380 check_non_negative(
1381 defaults_radius_lg,
1382 "defaults.border.corner_radius_lg",
1383 &mut missing,
1384 );
1385 check_non_negative(
1386 defaults_frame_width,
1387 "defaults.border.line_width",
1388 &mut missing,
1389 );
1390 check_non_negative(
1391 defaults_focus_ring_width,
1392 "defaults.focus_ring_width",
1393 &mut missing,
1394 );
1395 check_range_f32(
1400 defaults_disabled_opacity,
1401 0.0,
1402 1.0,
1403 "defaults.disabled_opacity",
1404 &mut missing,
1405 );
1406 check_range_f32(
1407 defaults_border_opacity,
1408 0.0,
1409 1.0,
1410 "defaults.border.opacity",
1411 &mut missing,
1412 );
1413
1414 check_non_negative(
1416 defaults_border_padding_h,
1417 "defaults.border.padding_horizontal",
1418 &mut missing,
1419 );
1420 check_non_negative(
1421 defaults_border_padding_v,
1422 "defaults.border.padding_vertical",
1423 &mut missing,
1424 );
1425
1426 check_non_negative(
1428 defaults_icon_sizes_toolbar,
1429 "defaults.icon_sizes.toolbar",
1430 &mut missing,
1431 );
1432 check_non_negative(
1433 defaults_icon_sizes_small,
1434 "defaults.icon_sizes.small",
1435 &mut missing,
1436 );
1437 check_non_negative(
1438 defaults_icon_sizes_large,
1439 "defaults.icon_sizes.large",
1440 &mut missing,
1441 );
1442 check_non_negative(
1443 defaults_icon_sizes_dialog,
1444 "defaults.icon_sizes.dialog",
1445 &mut missing,
1446 );
1447 check_non_negative(
1448 defaults_icon_sizes_panel,
1449 "defaults.icon_sizes.panel",
1450 &mut missing,
1451 );
1452
1453 check_positive(ts_caption.size, "text_scale.caption.size", &mut missing);
1455 check_positive(
1456 ts_caption.line_height,
1457 "text_scale.caption.line_height",
1458 &mut missing,
1459 );
1460 check_range_u16(
1461 ts_caption.weight,
1462 100,
1463 900,
1464 "text_scale.caption.weight",
1465 &mut missing,
1466 );
1467 check_positive(
1468 ts_section_heading.size,
1469 "text_scale.section_heading.size",
1470 &mut missing,
1471 );
1472 check_positive(
1473 ts_section_heading.line_height,
1474 "text_scale.section_heading.line_height",
1475 &mut missing,
1476 );
1477 check_range_u16(
1478 ts_section_heading.weight,
1479 100,
1480 900,
1481 "text_scale.section_heading.weight",
1482 &mut missing,
1483 );
1484 check_positive(
1485 ts_dialog_title.size,
1486 "text_scale.dialog_title.size",
1487 &mut missing,
1488 );
1489 check_positive(
1490 ts_dialog_title.line_height,
1491 "text_scale.dialog_title.line_height",
1492 &mut missing,
1493 );
1494 check_range_u16(
1495 ts_dialog_title.weight,
1496 100,
1497 900,
1498 "text_scale.dialog_title.weight",
1499 &mut missing,
1500 );
1501 check_positive(ts_display.size, "text_scale.display.size", &mut missing);
1502 check_positive(
1503 ts_display.line_height,
1504 "text_scale.display.line_height",
1505 &mut missing,
1506 );
1507 check_range_u16(
1508 ts_display.weight,
1509 100,
1510 900,
1511 "text_scale.display.weight",
1512 &mut missing,
1513 );
1514
1515 check_positive(
1517 window_title_bar_font.size,
1518 "window.title_bar_font.size",
1519 &mut missing,
1520 );
1521 check_range_u16(
1522 window_title_bar_font.weight,
1523 100,
1524 900,
1525 "window.title_bar_font.weight",
1526 &mut missing,
1527 );
1528
1529 check_non_negative(button_min_width, "button.min_width", &mut missing);
1531 check_non_negative(button_min_height, "button.min_height", &mut missing);
1532 check_non_negative(button_icon_spacing, "button.icon_text_gap", &mut missing);
1533 check_range_f32(
1534 button_disabled_opacity,
1535 0.0,
1536 1.0,
1537 "button.disabled_opacity",
1538 &mut missing,
1539 );
1540 check_positive(button_font.size, "button.font.size", &mut missing);
1541 check_range_u16(
1542 button_font.weight,
1543 100,
1544 900,
1545 "button.font.weight",
1546 &mut missing,
1547 );
1548
1549 check_non_negative(input_min_height, "input.min_height", &mut missing);
1551 check_range_f32(
1552 input_disabled_opacity,
1553 0.0,
1554 1.0,
1555 "input.disabled_opacity",
1556 &mut missing,
1557 );
1558 check_positive(input_font.size, "input.font.size", &mut missing);
1559 check_range_u16(
1560 input_font.weight,
1561 100,
1562 900,
1563 "input.font.weight",
1564 &mut missing,
1565 );
1566
1567 check_non_negative(
1569 checkbox_indicator_size,
1570 "checkbox.indicator_width",
1571 &mut missing,
1572 );
1573 check_non_negative(checkbox_spacing, "checkbox.label_gap", &mut missing);
1574 check_range_f32(
1575 checkbox_disabled_opacity,
1576 0.0,
1577 1.0,
1578 "checkbox.disabled_opacity",
1579 &mut missing,
1580 );
1581 check_positive(checkbox_font.size, "checkbox.font.size", &mut missing);
1582 check_range_u16(
1583 checkbox_font.weight,
1584 100,
1585 900,
1586 "checkbox.font.weight",
1587 &mut missing,
1588 );
1589
1590 check_non_negative(menu_item_height, "menu.row_height", &mut missing);
1592 check_non_negative(menu_icon_spacing, "menu.icon_text_gap", &mut missing);
1593 check_non_negative(menu_icon_size, "menu.icon_size", &mut missing);
1594 check_positive(menu_font.size, "menu.font.size", &mut missing);
1595 check_range_u16(menu_font.weight, 100, 900, "menu.font.weight", &mut missing);
1596
1597 check_non_negative(tooltip_max_width, "tooltip.max_width", &mut missing);
1599 check_positive(tooltip_font.size, "tooltip.font.size", &mut missing);
1600 check_range_u16(
1601 tooltip_font.weight,
1602 100,
1603 900,
1604 "tooltip.font.weight",
1605 &mut missing,
1606 );
1607
1608 check_non_negative(scrollbar_width, "scrollbar.groove_width", &mut missing);
1610 check_non_negative(
1611 scrollbar_min_thumb_height,
1612 "scrollbar.min_thumb_length",
1613 &mut missing,
1614 );
1615 check_non_negative(
1616 scrollbar_slider_width,
1617 "scrollbar.thumb_width",
1618 &mut missing,
1619 );
1620
1621 check_non_negative(slider_track_height, "slider.track_height", &mut missing);
1623 check_non_negative(slider_thumb_size, "slider.thumb_diameter", &mut missing);
1624 check_non_negative(slider_tick_length, "slider.tick_mark_length", &mut missing);
1625 check_range_f32(
1626 slider_disabled_opacity,
1627 0.0,
1628 1.0,
1629 "slider.disabled_opacity",
1630 &mut missing,
1631 );
1632
1633 check_non_negative(
1635 progress_bar_height,
1636 "progress_bar.track_height",
1637 &mut missing,
1638 );
1639 check_non_negative(
1640 progress_bar_min_width,
1641 "progress_bar.min_width",
1642 &mut missing,
1643 );
1644 check_non_negative(tab_min_width, "tab.min_width", &mut missing);
1648 check_non_negative(tab_min_height, "tab.min_height", &mut missing);
1649 check_positive(tab_font.size, "tab.font.size", &mut missing);
1650 check_range_u16(tab_font.weight, 100, 900, "tab.font.weight", &mut missing);
1651
1652 check_positive(sidebar_font.size, "sidebar.font.size", &mut missing);
1654 check_range_u16(
1655 sidebar_font.weight,
1656 100,
1657 900,
1658 "sidebar.font.weight",
1659 &mut missing,
1660 );
1661
1662 check_non_negative(toolbar_height, "toolbar.bar_height", &mut missing);
1664 check_non_negative(toolbar_item_spacing, "toolbar.item_gap", &mut missing);
1665 check_non_negative(toolbar_icon_size, "toolbar.icon_size", &mut missing);
1666 check_positive(toolbar_font.size, "toolbar.font.size", &mut missing);
1667 check_range_u16(
1668 toolbar_font.weight,
1669 100,
1670 900,
1671 "toolbar.font.weight",
1672 &mut missing,
1673 );
1674
1675 check_positive(status_bar_font.size, "status_bar.font.size", &mut missing);
1677 check_range_u16(
1678 status_bar_font.weight,
1679 100,
1680 900,
1681 "status_bar.font.weight",
1682 &mut missing,
1683 );
1684
1685 check_non_negative(list_item_height, "list.row_height", &mut missing);
1687 check_positive(list_item_font.size, "list.item_font.size", &mut missing);
1688 check_range_u16(
1689 list_item_font.weight,
1690 100,
1691 900,
1692 "list.item_font.weight",
1693 &mut missing,
1694 );
1695 check_positive(list_header_font.size, "list.header_font.size", &mut missing);
1696 check_range_u16(
1697 list_header_font.weight,
1698 100,
1699 900,
1700 "list.header_font.weight",
1701 &mut missing,
1702 );
1703
1704 check_positive(popover_font.size, "popover.font.size", &mut missing);
1706 check_range_u16(
1707 popover_font.weight,
1708 100,
1709 900,
1710 "popover.font.weight",
1711 &mut missing,
1712 );
1713
1714 check_non_negative(splitter_width, "splitter.divider_width", &mut missing);
1716
1717 check_non_negative(separator_line_width, "separator.line_width", &mut missing);
1719
1720 check_non_negative(switch_track_width, "switch.track_width", &mut missing);
1722 check_non_negative(switch_track_height, "switch.track_height", &mut missing);
1723 check_non_negative(switch_thumb_size, "switch.thumb_diameter", &mut missing);
1724 check_non_negative(switch_track_radius, "switch.track_radius", &mut missing);
1725 check_range_f32(
1726 switch_disabled_opacity,
1727 0.0,
1728 1.0,
1729 "switch.disabled_opacity",
1730 &mut missing,
1731 );
1732
1733 check_non_negative(dialog_min_width, "dialog.min_width", &mut missing);
1735 check_non_negative(dialog_max_width, "dialog.max_width", &mut missing);
1736 check_non_negative(dialog_min_height, "dialog.min_height", &mut missing);
1737 check_non_negative(dialog_max_height, "dialog.max_height", &mut missing);
1738 check_non_negative(dialog_button_spacing, "dialog.button_gap", &mut missing);
1739 check_non_negative(dialog_icon_size, "dialog.icon_size", &mut missing);
1740 check_positive(
1741 dialog_title_font.size,
1742 "dialog.title_font.size",
1743 &mut missing,
1744 );
1745 check_range_u16(
1746 dialog_title_font.weight,
1747 100,
1748 900,
1749 "dialog.title_font.weight",
1750 &mut missing,
1751 );
1752
1753 check_positive(dialog_body_font.size, "dialog.body_font.size", &mut missing);
1755 check_range_u16(
1756 dialog_body_font.weight,
1757 100,
1758 900,
1759 "dialog.body_font.weight",
1760 &mut missing,
1761 );
1762
1763 check_min_max(
1765 dialog_min_width,
1766 dialog_max_width,
1767 "dialog.min_width",
1768 "dialog.max_width",
1769 &mut missing,
1770 );
1771 check_min_max(
1772 dialog_min_height,
1773 dialog_max_height,
1774 "dialog.min_height",
1775 "dialog.max_height",
1776 &mut missing,
1777 );
1778
1779 check_non_negative(spinner_diameter, "spinner.diameter", &mut missing);
1781 check_non_negative(spinner_min_size, "spinner.min_diameter", &mut missing);
1782 check_non_negative(spinner_stroke_width, "spinner.stroke_width", &mut missing);
1783
1784 check_positive(link_font.size, "link.font.size", &mut missing);
1786 check_range_u16(link_font.weight, 100, 900, "link.font.weight", &mut missing);
1787
1788 check_non_negative(combo_box_min_height, "combo_box.min_height", &mut missing);
1790 check_non_negative(combo_box_min_width, "combo_box.min_width", &mut missing);
1791 check_non_negative(
1792 combo_box_arrow_size,
1793 "combo_box.arrow_icon_size",
1794 &mut missing,
1795 );
1796 check_non_negative(
1797 combo_box_arrow_area_width,
1798 "combo_box.arrow_area_width",
1799 &mut missing,
1800 );
1801 check_range_f32(
1802 combo_box_disabled_opacity,
1803 0.0,
1804 1.0,
1805 "combo_box.disabled_opacity",
1806 &mut missing,
1807 );
1808 check_positive(combo_box_font.size, "combo_box.font.size", &mut missing);
1809 check_range_u16(
1810 combo_box_font.weight,
1811 100,
1812 900,
1813 "combo_box.font.weight",
1814 &mut missing,
1815 );
1816
1817 check_non_negative(
1819 segmented_control_segment_height,
1820 "segmented_control.segment_height",
1821 &mut missing,
1822 );
1823 check_non_negative(
1824 segmented_control_separator_width,
1825 "segmented_control.separator_width",
1826 &mut missing,
1827 );
1828 check_range_f32(
1829 segmented_control_disabled_opacity,
1830 0.0,
1831 1.0,
1832 "segmented_control.disabled_opacity",
1833 &mut missing,
1834 );
1835 check_positive(
1836 segmented_control_font.size,
1837 "segmented_control.font.size",
1838 &mut missing,
1839 );
1840 check_range_u16(
1841 segmented_control_font.weight,
1842 100,
1843 900,
1844 "segmented_control.font.weight",
1845 &mut missing,
1846 );
1847
1848 check_non_negative(
1850 expander_header_height,
1851 "expander.header_height",
1852 &mut missing,
1853 );
1854 check_non_negative(
1855 expander_arrow_size,
1856 "expander.arrow_icon_size",
1857 &mut missing,
1858 );
1859 check_positive(expander_font.size, "expander.font.size", &mut missing);
1860 check_range_u16(
1861 expander_font.weight,
1862 100,
1863 900,
1864 "expander.font.weight",
1865 &mut missing,
1866 );
1867
1868 if !missing.is_empty() {
1873 return Err(crate::Error::Resolution(ThemeResolutionError {
1874 missing_fields: missing,
1875 }));
1876 }
1877
1878 Ok(ResolvedThemeVariant {
1883 defaults: ResolvedThemeDefaults {
1884 font: defaults_font,
1885 line_height: defaults_line_height,
1886 mono_font: defaults_mono_font,
1887 background_color: defaults_background,
1888 text_color: defaults_foreground,
1889 accent_color: defaults_accent,
1890 accent_text_color: defaults_accent_foreground,
1891 surface_color: defaults_surface,
1892 border: ResolvedBorderSpec {
1893 color: defaults_border,
1894 corner_radius: defaults_radius,
1895 corner_radius_lg: defaults_radius_lg,
1896 line_width: defaults_frame_width,
1897 opacity: defaults_border_opacity,
1898 shadow_enabled: defaults_shadow_enabled,
1899 padding_horizontal: defaults_border_padding_h,
1900 padding_vertical: defaults_border_padding_v,
1901 },
1902 muted_color: defaults_muted,
1903 shadow_color: defaults_shadow,
1904 link_color: defaults_link,
1905 selection_background: defaults_selection,
1906 selection_text_color: defaults_selection_foreground,
1907 selection_inactive_background: defaults_selection_inactive,
1908 text_selection_background: defaults_text_selection_background,
1909 text_selection_color: defaults_text_selection_color,
1910 disabled_text_color: defaults_disabled_foreground,
1911 danger_color: defaults_danger,
1912 danger_text_color: defaults_danger_foreground,
1913 warning_color: defaults_warning,
1914 warning_text_color: defaults_warning_foreground,
1915 success_color: defaults_success,
1916 success_text_color: defaults_success_foreground,
1917 info_color: defaults_info,
1918 info_text_color: defaults_info_foreground,
1919 disabled_opacity: defaults_disabled_opacity,
1920 focus_ring_color: defaults_focus_ring_color,
1921 focus_ring_width: defaults_focus_ring_width,
1922 focus_ring_offset: defaults_focus_ring_offset,
1923 icon_sizes: ResolvedIconSizes {
1924 toolbar: defaults_icon_sizes_toolbar,
1925 small: defaults_icon_sizes_small,
1926 large: defaults_icon_sizes_large,
1927 dialog: defaults_icon_sizes_dialog,
1928 panel: defaults_icon_sizes_panel,
1929 },
1930 font_dpi: defaults_font_dpi,
1931 text_scaling_factor: defaults_text_scaling_factor,
1932 reduce_motion: defaults_reduce_motion,
1933 high_contrast: defaults_high_contrast,
1934 reduce_transparency: defaults_reduce_transparency,
1935 },
1936 text_scale: ResolvedTextScale {
1937 caption: ts_caption,
1938 section_heading: ts_section_heading,
1939 dialog_title: ts_dialog_title,
1940 display: ts_display,
1941 },
1942 window: crate::model::widgets::ResolvedWindowTheme {
1943 background_color: window_background,
1944 title_bar_background: window_title_bar_background,
1945 inactive_title_bar_background: window_inactive_title_bar_background,
1946 inactive_title_bar_text_color: window_inactive_title_bar_foreground,
1947 title_bar_font: window_title_bar_font,
1948 border: window_border_spec,
1949 },
1950 button: crate::model::widgets::ResolvedButtonTheme {
1951 background_color: button_background,
1952 primary_background: button_primary_background,
1953 primary_text_color: button_primary_foreground,
1954 min_width: button_min_width,
1955 min_height: button_min_height,
1956 icon_text_gap: button_icon_spacing,
1957 disabled_opacity: button_disabled_opacity,
1958 hover_background: button_hover_background,
1959 hover_text_color: button_hover_text_color,
1960 active_text_color: button_active_text_color,
1961 disabled_text_color: button_disabled_text_color,
1962 active_background: self.button.active_background,
1964 disabled_background: self.button.disabled_background,
1965 font: button_font,
1966 border: button_border_spec,
1967 },
1968 input: crate::model::widgets::ResolvedInputTheme {
1969 background_color: input_background,
1970 placeholder_color: input_placeholder,
1971 caret_color: input_caret,
1972 selection_background: input_selection,
1973 selection_text_color: input_selection_foreground,
1974 min_height: input_min_height,
1975 disabled_opacity: input_disabled_opacity,
1976 disabled_text_color: input_disabled_text_color,
1977 hover_border_color: self.input.hover_border_color,
1979 focus_border_color: self.input.focus_border_color,
1980 disabled_background: self.input.disabled_background,
1981 font: input_font,
1982 border: input_border_spec,
1983 },
1984 checkbox: crate::model::widgets::ResolvedCheckboxTheme {
1985 background_color: checkbox_background_color,
1986 checked_background: checkbox_checked_background,
1987 indicator_color: checkbox_indicator_color,
1988 indicator_width: checkbox_indicator_size,
1989 label_gap: checkbox_spacing,
1990 disabled_opacity: checkbox_disabled_opacity,
1991 disabled_text_color: checkbox_disabled_text_color,
1992 hover_background: self.checkbox.hover_background,
1994 disabled_background: self.checkbox.disabled_background,
1995 unchecked_background: self.checkbox.unchecked_background,
1996 unchecked_border_color: self.checkbox.unchecked_border_color,
1997 font: checkbox_font,
1998 border: checkbox_border_spec,
1999 },
2000 menu: crate::model::widgets::ResolvedMenuTheme {
2001 background_color: menu_background,
2002 separator_color: menu_separator,
2003 row_height: menu_item_height,
2004 icon_text_gap: menu_icon_spacing,
2005 icon_size: menu_icon_size,
2006 hover_background: menu_hover_background,
2007 hover_text_color: menu_hover_text_color,
2008 disabled_text_color: menu_disabled_text_color,
2009 font: menu_font,
2010 border: menu_border_spec,
2011 },
2012 tooltip: crate::model::widgets::ResolvedTooltipTheme {
2013 background_color: tooltip_background,
2014 max_width: tooltip_max_width,
2015 font: tooltip_font,
2016 border: tooltip_border_spec,
2017 },
2018 scrollbar: crate::model::widgets::ResolvedScrollbarTheme {
2019 track_color: scrollbar_track,
2020 thumb_color: scrollbar_thumb,
2021 thumb_hover_color: scrollbar_thumb_hover,
2022 groove_width: scrollbar_width,
2023 min_thumb_length: scrollbar_min_thumb_height,
2024 thumb_width: scrollbar_slider_width,
2025 overlay_mode: scrollbar_overlay_mode,
2026 thumb_active_color: self.scrollbar.thumb_active_color,
2028 },
2029 slider: crate::model::widgets::ResolvedSliderTheme {
2030 fill_color: slider_fill,
2031 track_color: slider_track,
2032 thumb_color: slider_thumb,
2033 track_height: slider_track_height,
2034 thumb_diameter: slider_thumb_size,
2035 tick_mark_length: slider_tick_length,
2036 disabled_opacity: slider_disabled_opacity,
2037 thumb_hover_color: self.slider.thumb_hover_color,
2039 disabled_fill_color: self.slider.disabled_fill_color,
2040 disabled_track_color: self.slider.disabled_track_color,
2041 disabled_thumb_color: self.slider.disabled_thumb_color,
2042 },
2043 progress_bar: crate::model::widgets::ResolvedProgressBarTheme {
2044 fill_color: progress_bar_fill,
2045 track_color: progress_bar_track,
2046 track_height: progress_bar_height,
2047 min_width: progress_bar_min_width,
2048 border: progress_bar_border_spec,
2049 },
2050 tab: crate::model::widgets::ResolvedTabTheme {
2051 background_color: tab_background,
2052 active_background: tab_active_background,
2053 active_text_color: tab_active_foreground,
2054 bar_background: tab_bar_background,
2055 min_width: tab_min_width,
2056 min_height: tab_min_height,
2057 hover_text_color: tab_hover_text_color,
2058 hover_background: self.tab.hover_background,
2059 font: tab_font,
2060 border: tab_border_spec,
2061 },
2062 sidebar: crate::model::widgets::ResolvedSidebarTheme {
2063 background_color: sidebar_background,
2064 selection_background: sidebar_selection_background,
2065 selection_text_color: sidebar_selection_text_color,
2066 hover_background: sidebar_hover_background,
2067 font: sidebar_font,
2068 border: sidebar_border_spec,
2069 },
2070 toolbar: crate::model::widgets::ResolvedToolbarTheme {
2071 background_color: toolbar_background_color,
2072 bar_height: toolbar_height,
2073 item_gap: toolbar_item_spacing,
2074 icon_size: toolbar_icon_size,
2075 font: toolbar_font,
2076 border: toolbar_border_spec,
2077 },
2078 status_bar: crate::model::widgets::ResolvedStatusBarTheme {
2079 background_color: status_bar_background_color,
2080 font: status_bar_font,
2081 border: status_bar_border_spec,
2082 },
2083 list: crate::model::widgets::ResolvedListTheme {
2084 background_color: list_background,
2085 alternate_row_background: list_alternate_row,
2086 selection_background: list_selection,
2087 selection_text_color: list_selection_foreground,
2088 header_background: list_header_background,
2089 grid_color: list_grid_color,
2090 row_height: list_item_height,
2091 hover_background: list_hover_background,
2092 hover_text_color: list_hover_text_color,
2093 disabled_text_color: list_disabled_text_color,
2094 item_font: list_item_font,
2095 header_font: list_header_font,
2096 border: list_border_spec,
2097 },
2098 popover: crate::model::widgets::ResolvedPopoverTheme {
2099 background_color: popover_background,
2100 font: popover_font,
2101 border: popover_border_spec,
2102 },
2103 splitter: crate::model::widgets::ResolvedSplitterTheme {
2104 divider_width: splitter_width,
2105 divider_color: splitter_divider_color,
2106 hover_color: splitter_hover_color,
2107 },
2108 separator: crate::model::widgets::ResolvedSeparatorTheme {
2109 line_color: separator_color,
2110 line_width: separator_line_width,
2111 },
2112 switch: crate::model::widgets::ResolvedSwitchTheme {
2113 checked_background: switch_checked_background,
2114 unchecked_background: switch_unchecked_background,
2115 thumb_background: switch_thumb_background,
2116 track_width: switch_track_width,
2117 track_height: switch_track_height,
2118 thumb_diameter: switch_thumb_size,
2119 track_radius: switch_track_radius,
2120 disabled_opacity: switch_disabled_opacity,
2121 hover_checked_background: self.switch.hover_checked_background,
2122 hover_unchecked_background: self.switch.hover_unchecked_background,
2123 disabled_checked_background: self.switch.disabled_checked_background,
2124 disabled_unchecked_background: self.switch.disabled_unchecked_background,
2125 disabled_thumb_color: self.switch.disabled_thumb_color,
2126 },
2127 dialog: crate::model::widgets::ResolvedDialogTheme {
2128 background_color: dialog_background_color,
2129 min_width: dialog_min_width,
2130 max_width: dialog_max_width,
2131 min_height: dialog_min_height,
2132 max_height: dialog_max_height,
2133 button_gap: dialog_button_spacing,
2134 icon_size: dialog_icon_size,
2135 button_order: dialog_button_order,
2136 title_font: dialog_title_font,
2137 body_font: dialog_body_font,
2138 border: dialog_border_spec,
2139 },
2140 spinner: crate::model::widgets::ResolvedSpinnerTheme {
2141 fill_color: spinner_fill,
2142 diameter: spinner_diameter,
2143 min_diameter: spinner_min_size,
2144 stroke_width: spinner_stroke_width,
2145 },
2146 combo_box: crate::model::widgets::ResolvedComboBoxTheme {
2147 background_color: combo_box_background_color,
2148 min_height: combo_box_min_height,
2149 min_width: combo_box_min_width,
2150 arrow_icon_size: combo_box_arrow_size,
2151 arrow_area_width: combo_box_arrow_area_width,
2152 disabled_opacity: combo_box_disabled_opacity,
2153 disabled_text_color: combo_box_disabled_text_color,
2154 hover_background: self.combo_box.hover_background,
2155 disabled_background: self.combo_box.disabled_background,
2156 font: combo_box_font,
2157 border: combo_box_border_spec,
2158 },
2159 segmented_control: crate::model::widgets::ResolvedSegmentedControlTheme {
2160 background_color: segmented_control_background_color,
2161 active_background: segmented_control_active_background,
2162 active_text_color: segmented_control_active_text_color,
2163 segment_height: segmented_control_segment_height,
2164 separator_width: segmented_control_separator_width,
2165 disabled_opacity: segmented_control_disabled_opacity,
2166 hover_background: self.segmented_control.hover_background,
2167 font: segmented_control_font,
2168 border: segmented_control_border_spec,
2169 },
2170 card: crate::model::widgets::ResolvedCardTheme {
2171 background_color: card_background,
2172 border: card_border_spec,
2173 },
2174 expander: crate::model::widgets::ResolvedExpanderTheme {
2175 header_height: expander_header_height,
2176 arrow_icon_size: expander_arrow_size,
2177 hover_background: self.expander.hover_background,
2178 arrow_color: self.expander.arrow_color,
2179 font: expander_font,
2180 border: expander_border_spec,
2181 },
2182 link: crate::model::widgets::ResolvedLinkTheme {
2183 visited_text_color: link_visited,
2184 underline_enabled: link_underline,
2185 background_color: link_background,
2186 hover_background: link_hover_bg,
2187 hover_text_color: link_hover_text_color,
2188 active_text_color: link_active_text_color,
2189 disabled_text_color: link_disabled_text_color,
2190 font: link_font,
2191 },
2192 icon_set,
2193 icon_theme,
2194 })
2195 }
2196}