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