1use super::font::ResolvedFontSpec;
8use crate::Rgba;
9
10#[derive(Clone, Debug, PartialEq, serde::Serialize)]
14pub struct ResolvedThemeSpacing {
15 pub xxs: f32,
17 pub xs: f32,
19 pub s: f32,
21 pub m: f32,
23 pub l: f32,
25 pub xl: f32,
27 pub xxl: f32,
29}
30
31#[derive(Clone, Debug, PartialEq, serde::Serialize)]
35pub struct ResolvedIconSizes {
36 pub toolbar: f32,
38 pub small: f32,
40 pub large: f32,
42 pub dialog: f32,
44 pub panel: f32,
46}
47
48#[derive(Clone, Debug, Default, PartialEq, serde::Serialize)]
52pub struct ResolvedTextScaleEntry {
53 pub size: f32,
55 pub weight: u16,
57 pub line_height: f32,
59}
60
61#[derive(Clone, Debug, PartialEq, serde::Serialize)]
65pub struct ResolvedTextScale {
66 pub caption: ResolvedTextScaleEntry,
68 pub section_heading: ResolvedTextScaleEntry,
70 pub dialog_title: ResolvedTextScaleEntry,
72 pub display: ResolvedTextScaleEntry,
74}
75
76#[derive(Clone, Debug, PartialEq, serde::Serialize)]
83pub struct ResolvedThemeDefaults {
84 pub font: ResolvedFontSpec,
87 pub line_height: f32,
89 pub mono_font: ResolvedFontSpec,
91
92 pub background: Rgba,
95 pub foreground: Rgba,
97 pub accent: Rgba,
99 pub accent_foreground: Rgba,
101 pub surface: Rgba,
103 pub border: Rgba,
105 pub muted: Rgba,
107 pub shadow: Rgba,
109 pub link: Rgba,
111 pub selection: Rgba,
113 pub selection_foreground: Rgba,
115 pub selection_inactive: Rgba,
117 pub disabled_foreground: Rgba,
119
120 pub danger: Rgba,
123 pub danger_foreground: Rgba,
125 pub warning: Rgba,
127 pub warning_foreground: Rgba,
129 pub success: Rgba,
131 pub success_foreground: Rgba,
133 pub info: Rgba,
135 pub info_foreground: Rgba,
137
138 pub radius: f32,
141 pub radius_lg: f32,
143 pub frame_width: f32,
145 pub disabled_opacity: f32,
147 pub border_opacity: f32,
149 pub shadow_enabled: bool,
151
152 pub focus_ring_color: Rgba,
155 pub focus_ring_width: f32,
157 pub focus_ring_offset: f32,
159
160 pub spacing: ResolvedThemeSpacing,
163
164 pub icon_sizes: ResolvedIconSizes,
167
168 pub text_scaling_factor: f32,
171 pub reduce_motion: bool,
173 pub high_contrast: bool,
175 pub reduce_transparency: bool,
177}
178
179#[derive(Clone, Debug, PartialEq, serde::Serialize)]
187pub struct ResolvedThemeVariant {
188 pub defaults: ResolvedThemeDefaults,
190 pub text_scale: ResolvedTextScale,
192
193 pub window: super::widgets::ResolvedWindowTheme,
196 pub button: super::widgets::ResolvedButtonTheme,
198 pub input: super::widgets::ResolvedInputTheme,
200 pub checkbox: super::widgets::ResolvedCheckboxTheme,
202 pub menu: super::widgets::ResolvedMenuTheme,
204 pub tooltip: super::widgets::ResolvedTooltipTheme,
206 pub scrollbar: super::widgets::ResolvedScrollbarTheme,
208 pub slider: super::widgets::ResolvedSliderTheme,
210 pub progress_bar: super::widgets::ResolvedProgressBarTheme,
212 pub tab: super::widgets::ResolvedTabTheme,
214 pub sidebar: super::widgets::ResolvedSidebarTheme,
216 pub toolbar: super::widgets::ResolvedToolbarTheme,
218 pub status_bar: super::widgets::ResolvedStatusBarTheme,
220 pub list: super::widgets::ResolvedListTheme,
222 pub popover: super::widgets::ResolvedPopoverTheme,
224 pub splitter: super::widgets::ResolvedSplitterTheme,
226 pub separator: super::widgets::ResolvedSeparatorTheme,
228 pub switch: super::widgets::ResolvedSwitchTheme,
230 pub dialog: super::widgets::ResolvedDialogTheme,
232 pub spinner: super::widgets::ResolvedSpinnerTheme,
234 pub combo_box: super::widgets::ResolvedComboBoxTheme,
236 pub segmented_control: super::widgets::ResolvedSegmentedControlTheme,
238 pub card: super::widgets::ResolvedCardTheme,
240 pub expander: super::widgets::ResolvedExpanderTheme,
242 pub link: super::widgets::ResolvedLinkTheme,
244
245 pub icon_set: String,
247
248 pub icon_theme: String,
250}
251
252#[cfg(test)]
253#[allow(
254 clippy::unwrap_used,
255 clippy::expect_used,
256 clippy::bool_assert_comparison
257)]
258mod tests {
259 use super::*;
260 use crate::Rgba;
261 use crate::model::DialogButtonOrder;
262 use crate::model::ResolvedFontSpec;
263 use crate::model::widgets::{
264 ResolvedButtonTheme, ResolvedCardTheme, ResolvedCheckboxTheme, ResolvedComboBoxTheme,
265 ResolvedDialogTheme, ResolvedExpanderTheme, ResolvedInputTheme, ResolvedLinkTheme,
266 ResolvedListTheme, ResolvedMenuTheme, ResolvedPopoverTheme, ResolvedProgressBarTheme,
267 ResolvedScrollbarTheme, ResolvedSegmentedControlTheme, ResolvedSeparatorTheme,
268 ResolvedSidebarTheme, ResolvedSliderTheme, ResolvedSpinnerTheme, ResolvedSplitterTheme,
269 ResolvedStatusBarTheme, ResolvedSwitchTheme, ResolvedTabTheme, ResolvedToolbarTheme,
270 ResolvedTooltipTheme, ResolvedWindowTheme,
271 };
272
273 fn sample_font() -> ResolvedFontSpec {
274 ResolvedFontSpec {
275 family: "Inter".into(),
276 size: 14.0,
277 weight: 400,
278 }
279 }
280
281 fn sample_spacing() -> ResolvedThemeSpacing {
282 ResolvedThemeSpacing {
283 xxs: 2.0,
284 xs: 4.0,
285 s: 6.0,
286 m: 12.0,
287 l: 18.0,
288 xl: 24.0,
289 xxl: 36.0,
290 }
291 }
292
293 fn sample_icon_sizes() -> ResolvedIconSizes {
294 ResolvedIconSizes {
295 toolbar: 24.0,
296 small: 16.0,
297 large: 32.0,
298 dialog: 22.0,
299 panel: 20.0,
300 }
301 }
302
303 fn sample_text_scale_entry() -> ResolvedTextScaleEntry {
304 ResolvedTextScaleEntry {
305 size: 12.0,
306 weight: 400,
307 line_height: 1.4,
308 }
309 }
310
311 fn sample_defaults() -> ResolvedThemeDefaults {
312 let c = Rgba::rgb(128, 128, 128);
313 ResolvedThemeDefaults {
314 font: sample_font(),
315 line_height: 1.4,
316 mono_font: ResolvedFontSpec {
317 family: "JetBrains Mono".into(),
318 size: 12.0,
319 weight: 400,
320 },
321 background: c,
322 foreground: c,
323 accent: c,
324 accent_foreground: c,
325 surface: c,
326 border: c,
327 muted: c,
328 shadow: c,
329 link: c,
330 selection: c,
331 selection_foreground: c,
332 selection_inactive: c,
333 disabled_foreground: c,
334 danger: c,
335 danger_foreground: c,
336 warning: c,
337 warning_foreground: c,
338 success: c,
339 success_foreground: c,
340 info: c,
341 info_foreground: c,
342 radius: 4.0,
343 radius_lg: 8.0,
344 frame_width: 1.0,
345 disabled_opacity: 0.5,
346 border_opacity: 0.15,
347 shadow_enabled: true,
348 focus_ring_color: c,
349 focus_ring_width: 2.0,
350 focus_ring_offset: 1.0,
351 spacing: sample_spacing(),
352 icon_sizes: sample_icon_sizes(),
353 text_scaling_factor: 1.0,
354 reduce_motion: false,
355 high_contrast: false,
356 reduce_transparency: false,
357 }
358 }
359
360 #[test]
363 fn resolved_spacing_has_7_concrete_fields() {
364 let s = sample_spacing();
365 assert_eq!(s.xxs, 2.0);
366 assert_eq!(s.xs, 4.0);
367 assert_eq!(s.s, 6.0);
368 assert_eq!(s.m, 12.0);
369 assert_eq!(s.l, 18.0);
370 assert_eq!(s.xl, 24.0);
371 assert_eq!(s.xxl, 36.0);
372 }
373
374 #[test]
375 fn resolved_spacing_derives_clone_debug_partialeq() {
376 let s = sample_spacing();
377 let s2 = s.clone();
378 assert_eq!(s, s2);
379 let dbg = format!("{s:?}");
380 assert!(dbg.contains("ResolvedThemeSpacing"));
381 }
382
383 #[test]
386 fn resolved_icon_sizes_has_5_concrete_fields() {
387 let i = sample_icon_sizes();
388 assert_eq!(i.toolbar, 24.0);
389 assert_eq!(i.small, 16.0);
390 assert_eq!(i.large, 32.0);
391 assert_eq!(i.dialog, 22.0);
392 assert_eq!(i.panel, 20.0);
393 }
394
395 #[test]
396 fn resolved_icon_sizes_derives_clone_debug_partialeq() {
397 let i = sample_icon_sizes();
398 let i2 = i.clone();
399 assert_eq!(i, i2);
400 let dbg = format!("{i:?}");
401 assert!(dbg.contains("ResolvedIconSizes"));
402 }
403
404 #[test]
407 fn resolved_text_scale_entry_has_3_concrete_fields() {
408 let e = sample_text_scale_entry();
409 assert_eq!(e.size, 12.0);
410 assert_eq!(e.weight, 400);
411 assert_eq!(e.line_height, 1.4);
412 }
413
414 #[test]
415 fn resolved_text_scale_entry_derives_clone_debug_partialeq() {
416 let e = sample_text_scale_entry();
417 let e2 = e.clone();
418 assert_eq!(e, e2);
419 let dbg = format!("{e:?}");
420 assert!(dbg.contains("ResolvedTextScaleEntry"));
421 }
422
423 #[test]
426 fn resolved_text_scale_has_4_entries() {
427 let ts = ResolvedTextScale {
428 caption: ResolvedTextScaleEntry {
429 size: 11.0,
430 weight: 400,
431 line_height: 1.3,
432 },
433 section_heading: ResolvedTextScaleEntry {
434 size: 14.0,
435 weight: 600,
436 line_height: 1.4,
437 },
438 dialog_title: ResolvedTextScaleEntry {
439 size: 16.0,
440 weight: 700,
441 line_height: 1.2,
442 },
443 display: ResolvedTextScaleEntry {
444 size: 24.0,
445 weight: 300,
446 line_height: 1.1,
447 },
448 };
449 assert_eq!(ts.caption.size, 11.0);
450 assert_eq!(ts.section_heading.weight, 600);
451 assert_eq!(ts.dialog_title.size, 16.0);
452 assert_eq!(ts.display.weight, 300);
453 }
454
455 #[test]
456 fn resolved_text_scale_derives_clone_debug_partialeq() {
457 let e = sample_text_scale_entry();
458 let ts = ResolvedTextScale {
459 caption: e.clone(),
460 section_heading: e.clone(),
461 dialog_title: e.clone(),
462 display: e,
463 };
464 let ts2 = ts.clone();
465 assert_eq!(ts, ts2);
466 let dbg = format!("{ts:?}");
467 assert!(dbg.contains("ResolvedTextScale"));
468 }
469
470 #[test]
473 fn resolved_defaults_all_fields_concrete() {
474 let d = sample_defaults();
475 assert_eq!(d.font.family, "Inter");
477 assert_eq!(d.mono_font.family, "JetBrains Mono");
478 assert_eq!(d.line_height, 1.4);
479 assert_eq!(d.background, Rgba::rgb(128, 128, 128));
481 assert_eq!(d.accent, Rgba::rgb(128, 128, 128));
482 assert_eq!(d.radius, 4.0);
484 assert_eq!(d.shadow_enabled, true);
485 assert_eq!(d.focus_ring_width, 2.0);
487 assert_eq!(d.spacing.m, 12.0);
489 assert_eq!(d.icon_sizes.toolbar, 24.0);
490 assert_eq!(d.text_scaling_factor, 1.0);
492 assert_eq!(d.reduce_motion, false);
493 }
494
495 #[test]
496 fn resolved_defaults_derives_clone_debug_partialeq() {
497 let d = sample_defaults();
498 let d2 = d.clone();
499 assert_eq!(d, d2);
500 let dbg = format!("{d:?}");
501 assert!(dbg.contains("ResolvedThemeDefaults"));
502 }
503
504 #[test]
507 fn resolved_theme_construction_with_all_widgets() {
508 let c = Rgba::rgb(100, 100, 100);
509 let f = sample_font();
510 let e = sample_text_scale_entry();
511
512 let theme = ResolvedThemeVariant {
513 defaults: sample_defaults(),
514 text_scale: ResolvedTextScale {
515 caption: e.clone(),
516 section_heading: e.clone(),
517 dialog_title: e.clone(),
518 display: e,
519 },
520 window: ResolvedWindowTheme {
521 background: c,
522 foreground: c,
523 border: c,
524 title_bar_background: c,
525 title_bar_foreground: c,
526 inactive_title_bar_background: c,
527 inactive_title_bar_foreground: c,
528 radius: 4.0,
529 shadow: true,
530 title_bar_font: f.clone(),
531 },
532 button: ResolvedButtonTheme {
533 background: c,
534 foreground: c,
535 border: c,
536 primary_bg: c,
537 primary_fg: c,
538 min_width: 64.0,
539 min_height: 28.0,
540 padding_horizontal: 12.0,
541 padding_vertical: 6.0,
542 radius: 4.0,
543 icon_spacing: 6.0,
544 disabled_opacity: 0.5,
545 shadow: false,
546 font: f.clone(),
547 },
548 input: ResolvedInputTheme {
549 background: c,
550 foreground: c,
551 border: c,
552 placeholder: c,
553 caret: c,
554 selection: c,
555 selection_foreground: c,
556 min_height: 28.0,
557 padding_horizontal: 8.0,
558 padding_vertical: 4.0,
559 radius: 4.0,
560 border_width: 1.0,
561 font: f.clone(),
562 },
563 checkbox: ResolvedCheckboxTheme {
564 checked_bg: c,
565 indicator_size: 18.0,
566 spacing: 6.0,
567 radius: 2.0,
568 border_width: 1.0,
569 },
570 menu: ResolvedMenuTheme {
571 background: c,
572 foreground: c,
573 separator: c,
574 item_height: 28.0,
575 padding_horizontal: 8.0,
576 padding_vertical: 4.0,
577 icon_spacing: 6.0,
578 font: f.clone(),
579 },
580 tooltip: ResolvedTooltipTheme {
581 background: c,
582 foreground: c,
583 padding_horizontal: 6.0,
584 padding_vertical: 4.0,
585 max_width: 300.0,
586 radius: 4.0,
587 font: f.clone(),
588 },
589 scrollbar: ResolvedScrollbarTheme {
590 track: c,
591 thumb: c,
592 thumb_hover: c,
593 width: 14.0,
594 min_thumb_height: 20.0,
595 slider_width: 8.0,
596 overlay_mode: false,
597 },
598 slider: ResolvedSliderTheme {
599 fill: c,
600 track: c,
601 thumb: c,
602 track_height: 4.0,
603 thumb_size: 16.0,
604 tick_length: 6.0,
605 },
606 progress_bar: ResolvedProgressBarTheme {
607 fill: c,
608 track: c,
609 height: 6.0,
610 min_width: 100.0,
611 radius: 3.0,
612 },
613 tab: ResolvedTabTheme {
614 background: c,
615 foreground: c,
616 active_background: c,
617 active_foreground: c,
618 bar_background: c,
619 min_width: 60.0,
620 min_height: 32.0,
621 padding_horizontal: 12.0,
622 padding_vertical: 6.0,
623 },
624 sidebar: ResolvedSidebarTheme {
625 background: c,
626 foreground: c,
627 },
628 toolbar: ResolvedToolbarTheme {
629 height: 40.0,
630 item_spacing: 4.0,
631 padding: 4.0,
632 font: f.clone(),
633 },
634 status_bar: ResolvedStatusBarTheme { font: f.clone() },
635 list: ResolvedListTheme {
636 background: c,
637 foreground: c,
638 alternate_row: c,
639 selection: c,
640 selection_foreground: c,
641 header_background: c,
642 header_foreground: c,
643 grid_color: c,
644 item_height: 28.0,
645 padding_horizontal: 8.0,
646 padding_vertical: 4.0,
647 },
648 popover: ResolvedPopoverTheme {
649 background: c,
650 foreground: c,
651 border: c,
652 radius: 6.0,
653 },
654 splitter: ResolvedSplitterTheme { width: 4.0 },
655 separator: ResolvedSeparatorTheme { color: c },
656 switch: ResolvedSwitchTheme {
657 checked_bg: c,
658 unchecked_bg: c,
659 thumb_bg: c,
660 track_width: 40.0,
661 track_height: 20.0,
662 thumb_size: 14.0,
663 track_radius: 10.0,
664 },
665 dialog: ResolvedDialogTheme {
666 min_width: 320.0,
667 max_width: 600.0,
668 min_height: 200.0,
669 max_height: 800.0,
670 content_padding: 16.0,
671 button_spacing: 8.0,
672 radius: 8.0,
673 icon_size: 22.0,
674 button_order: DialogButtonOrder::TrailingAffirmative,
675 title_font: f.clone(),
676 },
677 spinner: ResolvedSpinnerTheme {
678 fill: c,
679 diameter: 24.0,
680 min_size: 16.0,
681 stroke_width: 2.0,
682 },
683 combo_box: ResolvedComboBoxTheme {
684 min_height: 28.0,
685 min_width: 80.0,
686 padding_horizontal: 8.0,
687 arrow_size: 12.0,
688 arrow_area_width: 20.0,
689 radius: 4.0,
690 },
691 segmented_control: ResolvedSegmentedControlTheme {
692 segment_height: 28.0,
693 separator_width: 1.0,
694 padding_horizontal: 12.0,
695 radius: 4.0,
696 },
697 card: ResolvedCardTheme {
698 background: c,
699 border: c,
700 radius: 8.0,
701 padding: 12.0,
702 shadow: true,
703 },
704 expander: ResolvedExpanderTheme {
705 header_height: 32.0,
706 arrow_size: 12.0,
707 content_padding: 8.0,
708 radius: 4.0,
709 },
710 link: ResolvedLinkTheme {
711 color: c,
712 visited: c,
713 background: c,
714 hover_bg: c,
715 underline: true,
716 },
717 icon_set: "freedesktop".into(),
718 icon_theme: "breeze".into(),
719 };
720
721 assert_eq!(theme.defaults.font.family, "Inter");
723 assert_eq!(theme.window.radius, 4.0);
724 assert_eq!(theme.button.min_height, 28.0);
725 assert_eq!(theme.icon_set, "freedesktop");
726 assert_eq!(theme.icon_theme, "breeze");
727 assert_eq!(theme.text_scale.caption.size, 12.0);
728 }
729
730 #[test]
731 fn resolved_theme_derives_clone_debug_partialeq() {
732 let c = Rgba::rgb(100, 100, 100);
733 let f = sample_font();
734 let e = sample_text_scale_entry();
735
736 let theme = ResolvedThemeVariant {
737 defaults: sample_defaults(),
738 text_scale: ResolvedTextScale {
739 caption: e.clone(),
740 section_heading: e.clone(),
741 dialog_title: e.clone(),
742 display: e,
743 },
744 window: ResolvedWindowTheme {
745 background: c,
746 foreground: c,
747 border: c,
748 title_bar_background: c,
749 title_bar_foreground: c,
750 inactive_title_bar_background: c,
751 inactive_title_bar_foreground: c,
752 radius: 4.0,
753 shadow: true,
754 title_bar_font: f.clone(),
755 },
756 button: ResolvedButtonTheme {
757 background: c,
758 foreground: c,
759 border: c,
760 primary_bg: c,
761 primary_fg: c,
762 min_width: 64.0,
763 min_height: 28.0,
764 padding_horizontal: 12.0,
765 padding_vertical: 6.0,
766 radius: 4.0,
767 icon_spacing: 6.0,
768 disabled_opacity: 0.5,
769 shadow: false,
770 font: f.clone(),
771 },
772 input: ResolvedInputTheme {
773 background: c,
774 foreground: c,
775 border: c,
776 placeholder: c,
777 caret: c,
778 selection: c,
779 selection_foreground: c,
780 min_height: 28.0,
781 padding_horizontal: 8.0,
782 padding_vertical: 4.0,
783 radius: 4.0,
784 border_width: 1.0,
785 font: f.clone(),
786 },
787 checkbox: ResolvedCheckboxTheme {
788 checked_bg: c,
789 indicator_size: 18.0,
790 spacing: 6.0,
791 radius: 2.0,
792 border_width: 1.0,
793 },
794 menu: ResolvedMenuTheme {
795 background: c,
796 foreground: c,
797 separator: c,
798 item_height: 28.0,
799 padding_horizontal: 8.0,
800 padding_vertical: 4.0,
801 icon_spacing: 6.0,
802 font: f.clone(),
803 },
804 tooltip: ResolvedTooltipTheme {
805 background: c,
806 foreground: c,
807 padding_horizontal: 6.0,
808 padding_vertical: 4.0,
809 max_width: 300.0,
810 radius: 4.0,
811 font: f.clone(),
812 },
813 scrollbar: ResolvedScrollbarTheme {
814 track: c,
815 thumb: c,
816 thumb_hover: c,
817 width: 14.0,
818 min_thumb_height: 20.0,
819 slider_width: 8.0,
820 overlay_mode: false,
821 },
822 slider: ResolvedSliderTheme {
823 fill: c,
824 track: c,
825 thumb: c,
826 track_height: 4.0,
827 thumb_size: 16.0,
828 tick_length: 6.0,
829 },
830 progress_bar: ResolvedProgressBarTheme {
831 fill: c,
832 track: c,
833 height: 6.0,
834 min_width: 100.0,
835 radius: 3.0,
836 },
837 tab: ResolvedTabTheme {
838 background: c,
839 foreground: c,
840 active_background: c,
841 active_foreground: c,
842 bar_background: c,
843 min_width: 60.0,
844 min_height: 32.0,
845 padding_horizontal: 12.0,
846 padding_vertical: 6.0,
847 },
848 sidebar: ResolvedSidebarTheme {
849 background: c,
850 foreground: c,
851 },
852 toolbar: ResolvedToolbarTheme {
853 height: 40.0,
854 item_spacing: 4.0,
855 padding: 4.0,
856 font: f.clone(),
857 },
858 status_bar: ResolvedStatusBarTheme { font: f.clone() },
859 list: ResolvedListTheme {
860 background: c,
861 foreground: c,
862 alternate_row: c,
863 selection: c,
864 selection_foreground: c,
865 header_background: c,
866 header_foreground: c,
867 grid_color: c,
868 item_height: 28.0,
869 padding_horizontal: 8.0,
870 padding_vertical: 4.0,
871 },
872 popover: ResolvedPopoverTheme {
873 background: c,
874 foreground: c,
875 border: c,
876 radius: 6.0,
877 },
878 splitter: ResolvedSplitterTheme { width: 4.0 },
879 separator: ResolvedSeparatorTheme { color: c },
880 switch: ResolvedSwitchTheme {
881 checked_bg: c,
882 unchecked_bg: c,
883 thumb_bg: c,
884 track_width: 40.0,
885 track_height: 20.0,
886 thumb_size: 14.0,
887 track_radius: 10.0,
888 },
889 dialog: ResolvedDialogTheme {
890 min_width: 320.0,
891 max_width: 600.0,
892 min_height: 200.0,
893 max_height: 800.0,
894 content_padding: 16.0,
895 button_spacing: 8.0,
896 radius: 8.0,
897 icon_size: 22.0,
898 button_order: DialogButtonOrder::TrailingAffirmative,
899 title_font: f.clone(),
900 },
901 spinner: ResolvedSpinnerTheme {
902 fill: c,
903 diameter: 24.0,
904 min_size: 16.0,
905 stroke_width: 2.0,
906 },
907 combo_box: ResolvedComboBoxTheme {
908 min_height: 28.0,
909 min_width: 80.0,
910 padding_horizontal: 8.0,
911 arrow_size: 12.0,
912 arrow_area_width: 20.0,
913 radius: 4.0,
914 },
915 segmented_control: ResolvedSegmentedControlTheme {
916 segment_height: 28.0,
917 separator_width: 1.0,
918 padding_horizontal: 12.0,
919 radius: 4.0,
920 },
921 card: ResolvedCardTheme {
922 background: c,
923 border: c,
924 radius: 8.0,
925 padding: 12.0,
926 shadow: true,
927 },
928 expander: ResolvedExpanderTheme {
929 header_height: 32.0,
930 arrow_size: 12.0,
931 content_padding: 8.0,
932 radius: 4.0,
933 },
934 link: ResolvedLinkTheme {
935 color: c,
936 visited: c,
937 background: c,
938 hover_bg: c,
939 underline: true,
940 },
941 icon_set: "freedesktop".into(),
942 icon_theme: "breeze".into(),
943 };
944
945 let theme2 = theme.clone();
946 assert_eq!(theme, theme2);
947 let dbg = format!("{theme:?}");
948 assert!(dbg.contains("ResolvedThemeVariant"));
949 }
950}