1mod color;
7mod theme;
8pub use color::{Color, ColorDepth};
9pub use theme::{Theme, ThemeBuilder};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub enum Breakpoint {
17 Xs,
19 Sm,
21 Md,
23 Lg,
25 Xl,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35pub enum Border {
36 Single,
38 Double,
40 Rounded,
42 Thick,
44 Dashed,
46 DashedThick,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55pub struct BorderChars {
56 pub tl: char,
58 pub tr: char,
60 pub bl: char,
62 pub br: char,
64 pub h: char,
66 pub v: char,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73pub struct BorderSides {
74 pub top: bool,
75 pub right: bool,
76 pub bottom: bool,
77 pub left: bool,
78}
79
80impl BorderSides {
81 pub const fn all() -> Self {
83 Self {
84 top: true,
85 right: true,
86 bottom: true,
87 left: true,
88 }
89 }
90
91 pub const fn none() -> Self {
93 Self {
94 top: false,
95 right: false,
96 bottom: false,
97 left: false,
98 }
99 }
100
101 pub const fn horizontal() -> Self {
103 Self {
104 top: true,
105 right: false,
106 bottom: true,
107 left: false,
108 }
109 }
110
111 pub const fn vertical() -> Self {
113 Self {
114 top: false,
115 right: true,
116 bottom: false,
117 left: true,
118 }
119 }
120
121 pub fn has_horizontal(&self) -> bool {
123 self.top || self.bottom
124 }
125
126 pub fn has_vertical(&self) -> bool {
128 self.left || self.right
129 }
130}
131
132impl Default for BorderSides {
133 fn default() -> Self {
134 Self::all()
135 }
136}
137
138impl Border {
139 pub const fn chars(self) -> BorderChars {
141 match self {
142 Self::Single => BorderChars {
143 tl: '┌',
144 tr: '┐',
145 bl: '└',
146 br: '┘',
147 h: '─',
148 v: '│',
149 },
150 Self::Double => BorderChars {
151 tl: '╔',
152 tr: '╗',
153 bl: '╚',
154 br: '╝',
155 h: '═',
156 v: '║',
157 },
158 Self::Rounded => BorderChars {
159 tl: '╭',
160 tr: '╮',
161 bl: '╰',
162 br: '╯',
163 h: '─',
164 v: '│',
165 },
166 Self::Thick => BorderChars {
167 tl: '┏',
168 tr: '┓',
169 bl: '┗',
170 br: '┛',
171 h: '━',
172 v: '┃',
173 },
174 Self::Dashed => BorderChars {
175 tl: '┌',
176 tr: '┐',
177 bl: '└',
178 br: '┘',
179 h: '┄',
180 v: '┆',
181 },
182 Self::DashedThick => BorderChars {
183 tl: '┏',
184 tr: '┓',
185 bl: '┗',
186 br: '┛',
187 h: '┅',
188 v: '┇',
189 },
190 }
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
199#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
200pub struct Padding {
201 pub top: u32,
203 pub right: u32,
205 pub bottom: u32,
207 pub left: u32,
209}
210
211impl Padding {
212 pub const fn all(v: u32) -> Self {
214 Self::new(v, v, v, v)
215 }
216
217 pub const fn xy(x: u32, y: u32) -> Self {
219 Self::new(y, x, y, x)
220 }
221
222 pub const fn new(top: u32, right: u32, bottom: u32, left: u32) -> Self {
224 Self {
225 top,
226 right,
227 bottom,
228 left,
229 }
230 }
231
232 pub const fn horizontal(self) -> u32 {
234 self.left + self.right
235 }
236
237 pub const fn vertical(self) -> u32 {
239 self.top + self.bottom
240 }
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
248#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
249pub struct Margin {
250 pub top: u32,
252 pub right: u32,
254 pub bottom: u32,
256 pub left: u32,
258}
259
260impl Margin {
261 pub const fn all(v: u32) -> Self {
263 Self::new(v, v, v, v)
264 }
265
266 pub const fn xy(x: u32, y: u32) -> Self {
268 Self::new(y, x, y, x)
269 }
270
271 pub const fn new(top: u32, right: u32, bottom: u32, left: u32) -> Self {
273 Self {
274 top,
275 right,
276 bottom,
277 left,
278 }
279 }
280
281 pub const fn horizontal(self) -> u32 {
283 self.left + self.right
284 }
285
286 pub const fn vertical(self) -> u32 {
288 self.top + self.bottom
289 }
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
305#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
306#[must_use = "configure constraints using the returned value"]
307pub struct Constraints {
308 pub min_width: Option<u32>,
310 pub max_width: Option<u32>,
312 pub min_height: Option<u32>,
314 pub max_height: Option<u32>,
316 pub width_pct: Option<u8>,
318 pub height_pct: Option<u8>,
320}
321
322impl Constraints {
323 pub const fn min_w(mut self, min_width: u32) -> Self {
325 self.min_width = Some(min_width);
326 self
327 }
328
329 pub const fn max_w(mut self, max_width: u32) -> Self {
331 self.max_width = Some(max_width);
332 self
333 }
334
335 pub const fn min_h(mut self, min_height: u32) -> Self {
337 self.min_height = Some(min_height);
338 self
339 }
340
341 pub const fn max_h(mut self, max_height: u32) -> Self {
343 self.max_height = Some(max_height);
344 self
345 }
346
347 pub const fn w_pct(mut self, pct: u8) -> Self {
349 self.width_pct = Some(pct);
350 self
351 }
352
353 pub const fn h_pct(mut self, pct: u8) -> Self {
355 self.height_pct = Some(pct);
356 self
357 }
358}
359
360#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
366#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
367pub enum Align {
368 #[default]
370 Start,
371 Center,
373 End,
375}
376
377#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
386#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
387pub enum Justify {
388 #[default]
390 Start,
391 Center,
393 End,
395 SpaceBetween,
397 SpaceAround,
399 SpaceEvenly,
401}
402
403#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
408#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
409#[cfg_attr(feature = "serde", serde(transparent))]
410pub struct Modifiers(pub u8);
411
412impl Modifiers {
413 pub const NONE: Self = Self(0);
415 pub const BOLD: Self = Self(1 << 0);
417 pub const DIM: Self = Self(1 << 1);
419 pub const ITALIC: Self = Self(1 << 2);
421 pub const UNDERLINE: Self = Self(1 << 3);
423 pub const REVERSED: Self = Self(1 << 4);
425 pub const STRIKETHROUGH: Self = Self(1 << 5);
427
428 #[inline]
430 pub fn contains(self, other: Self) -> bool {
431 (self.0 & other.0) == other.0
432 }
433
434 #[inline]
436 pub fn insert(&mut self, other: Self) {
437 self.0 |= other.0;
438 }
439
440 #[inline]
442 pub fn is_empty(self) -> bool {
443 self.0 == 0
444 }
445}
446
447impl std::ops::BitOr for Modifiers {
448 type Output = Self;
449 #[inline]
450 fn bitor(self, rhs: Self) -> Self {
451 Self(self.0 | rhs.0)
452 }
453}
454
455impl std::ops::BitOrAssign for Modifiers {
456 #[inline]
457 fn bitor_assign(&mut self, rhs: Self) {
458 self.0 |= rhs.0;
459 }
460}
461
462#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
476#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
477#[must_use = "build and pass the returned Style value"]
478pub struct Style {
479 pub fg: Option<Color>,
481 pub bg: Option<Color>,
483 pub modifiers: Modifiers,
485}
486
487impl Style {
488 pub const fn new() -> Self {
490 Self {
491 fg: None,
492 bg: None,
493 modifiers: Modifiers::NONE,
494 }
495 }
496
497 pub const fn fg(mut self, color: Color) -> Self {
499 self.fg = Some(color);
500 self
501 }
502
503 pub const fn bg(mut self, color: Color) -> Self {
505 self.bg = Some(color);
506 self
507 }
508
509 pub fn bold(mut self) -> Self {
511 self.modifiers |= Modifiers::BOLD;
512 self
513 }
514
515 pub fn dim(mut self) -> Self {
517 self.modifiers |= Modifiers::DIM;
518 self
519 }
520
521 pub fn italic(mut self) -> Self {
523 self.modifiers |= Modifiers::ITALIC;
524 self
525 }
526
527 pub fn underline(mut self) -> Self {
529 self.modifiers |= Modifiers::UNDERLINE;
530 self
531 }
532
533 pub fn reversed(mut self) -> Self {
535 self.modifiers |= Modifiers::REVERSED;
536 self
537 }
538
539 pub fn strikethrough(mut self) -> Self {
541 self.modifiers |= Modifiers::STRIKETHROUGH;
542 self
543 }
544}
545
546#[derive(Debug, Clone, Copy, Default)]
570pub struct ContainerStyle {
571 pub border: Option<Border>,
573 pub border_sides: Option<BorderSides>,
575 pub border_style: Option<Style>,
577 pub bg: Option<Color>,
579 pub text_color: Option<Color>,
581 pub dark_bg: Option<Color>,
583 pub dark_border_style: Option<Style>,
585 pub padding: Option<Padding>,
587 pub margin: Option<Margin>,
589 pub gap: Option<u32>,
591 pub row_gap: Option<u32>,
593 pub col_gap: Option<u32>,
595 pub grow: Option<u16>,
597 pub align: Option<Align>,
599 pub align_self: Option<Align>,
601 pub justify: Option<Justify>,
603 pub w: Option<u32>,
605 pub h: Option<u32>,
607 pub min_w: Option<u32>,
609 pub max_w: Option<u32>,
611 pub min_h: Option<u32>,
613 pub max_h: Option<u32>,
615 pub w_pct: Option<u8>,
617 pub h_pct: Option<u8>,
619}
620
621impl ContainerStyle {
622 pub const fn new() -> Self {
624 Self {
625 border: None,
626 border_sides: None,
627 border_style: None,
628 bg: None,
629 text_color: None,
630 dark_bg: None,
631 dark_border_style: None,
632 padding: None,
633 margin: None,
634 gap: None,
635 row_gap: None,
636 col_gap: None,
637 grow: None,
638 align: None,
639 align_self: None,
640 justify: None,
641 w: None,
642 h: None,
643 min_w: None,
644 max_w: None,
645 min_h: None,
646 max_h: None,
647 w_pct: None,
648 h_pct: None,
649 }
650 }
651
652 pub const fn border(mut self, border: Border) -> Self {
654 self.border = Some(border);
655 self
656 }
657
658 pub const fn border_sides(mut self, sides: BorderSides) -> Self {
660 self.border_sides = Some(sides);
661 self
662 }
663
664 pub const fn bg(mut self, color: Color) -> Self {
666 self.bg = Some(color);
667 self
668 }
669
670 pub const fn text_color(mut self, color: Color) -> Self {
672 self.text_color = Some(color);
673 self
674 }
675
676 pub const fn dark_bg(mut self, color: Color) -> Self {
678 self.dark_bg = Some(color);
679 self
680 }
681
682 pub const fn p(mut self, value: u32) -> Self {
684 self.padding = Some(Padding {
685 top: value,
686 bottom: value,
687 left: value,
688 right: value,
689 });
690 self
691 }
692
693 pub const fn px(mut self, value: u32) -> Self {
695 let p = match self.padding {
696 Some(p) => Padding {
697 left: value,
698 right: value,
699 ..p
700 },
701 None => Padding {
702 top: 0,
703 bottom: 0,
704 left: value,
705 right: value,
706 },
707 };
708 self.padding = Some(p);
709 self
710 }
711
712 pub const fn py(mut self, value: u32) -> Self {
714 let p = match self.padding {
715 Some(p) => Padding {
716 top: value,
717 bottom: value,
718 ..p
719 },
720 None => Padding {
721 top: value,
722 bottom: value,
723 left: 0,
724 right: 0,
725 },
726 };
727 self.padding = Some(p);
728 self
729 }
730
731 pub const fn m(mut self, value: u32) -> Self {
733 self.margin = Some(Margin {
734 top: value,
735 bottom: value,
736 left: value,
737 right: value,
738 });
739 self
740 }
741
742 pub const fn gap(mut self, value: u32) -> Self {
744 self.gap = Some(value);
745 self
746 }
747
748 pub const fn row_gap(mut self, value: u32) -> Self {
750 self.row_gap = Some(value);
751 self
752 }
753
754 pub const fn col_gap(mut self, value: u32) -> Self {
756 self.col_gap = Some(value);
757 self
758 }
759
760 pub const fn grow(mut self, value: u16) -> Self {
762 self.grow = Some(value);
763 self
764 }
765
766 pub const fn w(mut self, value: u32) -> Self {
768 self.w = Some(value);
769 self
770 }
771
772 pub const fn h(mut self, value: u32) -> Self {
774 self.h = Some(value);
775 self
776 }
777
778 pub const fn min_w(mut self, value: u32) -> Self {
780 self.min_w = Some(value);
781 self
782 }
783
784 pub const fn max_w(mut self, value: u32) -> Self {
786 self.max_w = Some(value);
787 self
788 }
789
790 pub const fn align(mut self, value: Align) -> Self {
792 self.align = Some(value);
793 self
794 }
795
796 pub const fn align_self(mut self, value: Align) -> Self {
798 self.align_self = Some(value);
799 self
800 }
801
802 pub const fn justify(mut self, value: Justify) -> Self {
804 self.justify = Some(value);
805 self
806 }
807
808 pub const fn min_h(mut self, value: u32) -> Self {
810 self.min_h = Some(value);
811 self
812 }
813
814 pub const fn max_h(mut self, value: u32) -> Self {
816 self.max_h = Some(value);
817 self
818 }
819
820 pub const fn w_pct(mut self, value: u8) -> Self {
822 self.w_pct = Some(value);
823 self
824 }
825
826 pub const fn h_pct(mut self, value: u8) -> Self {
828 self.h_pct = Some(value);
829 self
830 }
831}
832
833#[derive(Debug, Clone, Copy, Default)]
834#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
835pub struct WidgetColors {
837 pub fg: Option<Color>,
839 pub bg: Option<Color>,
841 pub border: Option<Color>,
843 pub accent: Option<Color>,
845}
846
847impl WidgetColors {
848 pub const fn new() -> Self {
850 Self {
851 fg: None,
852 bg: None,
853 border: None,
854 accent: None,
855 }
856 }
857
858 pub const fn fg(mut self, color: Color) -> Self {
860 self.fg = Some(color);
861 self
862 }
863
864 pub const fn bg(mut self, color: Color) -> Self {
866 self.bg = Some(color);
867 self
868 }
869
870 pub const fn border(mut self, color: Color) -> Self {
872 self.border = Some(color);
873 self
874 }
875
876 pub const fn accent(mut self, color: Color) -> Self {
878 self.accent = Some(color);
879 self
880 }
881}
882
883#[cfg(test)]
884mod tests {
885 use super::*;
886
887 #[test]
888 fn style_new_is_default() {
889 let style = Style::new();
890 assert_eq!(style.fg, None);
891 assert_eq!(style.bg, None);
892 assert_eq!(style.modifiers, Modifiers::NONE);
893 assert_eq!(style, Style::default());
894 }
895
896 #[test]
897 fn style_bold_and_fg_set_expected_fields() {
898 let style = Style::new().bold().fg(Color::Red);
899 assert_eq!(style.fg, Some(Color::Red));
900 assert_eq!(style.bg, None);
901 assert!(style.modifiers.contains(Modifiers::BOLD));
902 }
903
904 #[test]
905 fn style_multiple_modifiers_accumulate() {
906 let style = Style::new().italic().underline().dim();
907 assert!(style.modifiers.contains(Modifiers::ITALIC));
908 assert!(style.modifiers.contains(Modifiers::UNDERLINE));
909 assert!(style.modifiers.contains(Modifiers::DIM));
910 }
911
912 #[test]
913 fn style_repeated_fg_overrides_previous_color() {
914 let style = Style::new().fg(Color::Blue).fg(Color::Green);
915 assert_eq!(style.fg, Some(Color::Green));
916 }
917
918 #[test]
919 fn style_repeated_bg_overrides_previous_color() {
920 let style = Style::new().bg(Color::Blue).bg(Color::Green);
921 assert_eq!(style.bg, Some(Color::Green));
922 }
923
924 #[test]
925 fn style_override_preserves_existing_modifiers() {
926 let style = Style::new().bold().fg(Color::Red).fg(Color::Yellow);
927 assert_eq!(style.fg, Some(Color::Yellow));
928 assert!(style.modifiers.contains(Modifiers::BOLD));
929 }
930
931 #[test]
932 fn padding_all_sets_all_sides() {
933 let p = Padding::all(3);
934 assert_eq!(p.top, 3);
935 assert_eq!(p.right, 3);
936 assert_eq!(p.bottom, 3);
937 assert_eq!(p.left, 3);
938 }
939
940 #[test]
941 fn padding_xy_sets_axis_values() {
942 let p = Padding::xy(4, 2);
943 assert_eq!(p.top, 2);
944 assert_eq!(p.bottom, 2);
945 assert_eq!(p.left, 4);
946 assert_eq!(p.right, 4);
947 }
948
949 #[test]
950 fn padding_new_and_totals_are_correct() {
951 let p = Padding::new(1, 2, 3, 4);
952 assert_eq!(p.top, 1);
953 assert_eq!(p.right, 2);
954 assert_eq!(p.bottom, 3);
955 assert_eq!(p.left, 4);
956 assert_eq!(p.horizontal(), 6);
957 assert_eq!(p.vertical(), 4);
958 }
959
960 #[test]
961 fn margin_all_and_xy_are_correct() {
962 let all = Margin::all(5);
963 assert_eq!(all, Margin::new(5, 5, 5, 5));
964
965 let xy = Margin::xy(7, 1);
966 assert_eq!(xy.top, 1);
967 assert_eq!(xy.bottom, 1);
968 assert_eq!(xy.left, 7);
969 assert_eq!(xy.right, 7);
970 }
971
972 #[test]
973 fn margin_new_and_totals_are_correct() {
974 let m = Margin::new(2, 4, 6, 8);
975 assert_eq!(m.horizontal(), 12);
976 assert_eq!(m.vertical(), 8);
977 }
978
979 #[test]
980 fn constraints_min_max_builder_sets_values() {
981 let c = Constraints::default()
982 .min_w(10)
983 .max_w(40)
984 .min_h(5)
985 .max_h(20);
986 assert_eq!(c.min_width, Some(10));
987 assert_eq!(c.max_width, Some(40));
988 assert_eq!(c.min_height, Some(5));
989 assert_eq!(c.max_height, Some(20));
990 }
991
992 #[test]
993 fn constraints_percentage_builder_sets_values() {
994 let c = Constraints::default().w_pct(50).h_pct(80);
995 assert_eq!(c.width_pct, Some(50));
996 assert_eq!(c.height_pct, Some(80));
997 }
998
999 #[test]
1000 fn border_sides_all_has_both_axes() {
1001 let sides = BorderSides::all();
1002 assert!(sides.top && sides.right && sides.bottom && sides.left);
1003 assert!(sides.has_horizontal());
1004 assert!(sides.has_vertical());
1005 }
1006
1007 #[test]
1008 fn border_sides_none_has_no_axes() {
1009 let sides = BorderSides::none();
1010 assert!(!sides.top && !sides.right && !sides.bottom && !sides.left);
1011 assert!(!sides.has_horizontal());
1012 assert!(!sides.has_vertical());
1013 }
1014
1015 #[test]
1016 fn border_sides_horizontal_only() {
1017 let sides = BorderSides::horizontal();
1018 assert!(sides.top);
1019 assert!(sides.bottom);
1020 assert!(!sides.left);
1021 assert!(!sides.right);
1022 assert!(sides.has_horizontal());
1023 assert!(!sides.has_vertical());
1024 }
1025
1026 #[test]
1027 fn border_sides_vertical_only() {
1028 let sides = BorderSides::vertical();
1029 assert!(!sides.top);
1030 assert!(!sides.bottom);
1031 assert!(sides.left);
1032 assert!(sides.right);
1033 assert!(!sides.has_horizontal());
1034 assert!(sides.has_vertical());
1035 }
1036
1037 #[test]
1038 fn container_style_new_is_empty() {
1039 let s = ContainerStyle::new();
1040 assert_eq!(s.border, None);
1041 assert_eq!(s.bg, None);
1042 assert_eq!(s.padding, None);
1043 assert_eq!(s.margin, None);
1044 assert_eq!(s.gap, None);
1045 assert_eq!(s.align, None);
1046 assert_eq!(s.justify, None);
1047 }
1048
1049 #[test]
1050 fn container_style_const_construction_and_fields() {
1051 const CARD: ContainerStyle = ContainerStyle::new()
1052 .border(Border::Rounded)
1053 .border_sides(BorderSides::horizontal())
1054 .p(2)
1055 .m(1)
1056 .gap(3)
1057 .align(Align::Center)
1058 .justify(Justify::SpaceBetween)
1059 .w(60)
1060 .h(20);
1061
1062 assert_eq!(CARD.border, Some(Border::Rounded));
1063 assert_eq!(CARD.border_sides, Some(BorderSides::horizontal()));
1064 assert_eq!(CARD.padding, Some(Padding::all(2)));
1065 assert_eq!(CARD.margin, Some(Margin::all(1)));
1066 assert_eq!(CARD.gap, Some(3));
1067 assert_eq!(CARD.align, Some(Align::Center));
1068 assert_eq!(CARD.justify, Some(Justify::SpaceBetween));
1069 assert_eq!(CARD.w, Some(60));
1070 assert_eq!(CARD.h, Some(20));
1071 }
1072
1073 #[test]
1074 fn widget_colors_new_is_empty() {
1075 let colors = WidgetColors::new();
1076 assert_eq!(colors.fg, None);
1077 assert_eq!(colors.bg, None);
1078 assert_eq!(colors.border, None);
1079 assert_eq!(colors.accent, None);
1080
1081 let defaults = WidgetColors::default();
1082 assert_eq!(defaults.fg, None);
1083 assert_eq!(defaults.bg, None);
1084 assert_eq!(defaults.border, None);
1085 assert_eq!(defaults.accent, None);
1086 }
1087
1088 #[test]
1089 fn widget_colors_builder_sets_all_fields() {
1090 let colors = WidgetColors::new()
1091 .fg(Color::White)
1092 .bg(Color::Black)
1093 .border(Color::Cyan)
1094 .accent(Color::Yellow);
1095
1096 assert_eq!(colors.fg, Some(Color::White));
1097 assert_eq!(colors.bg, Some(Color::Black));
1098 assert_eq!(colors.border, Some(Color::Cyan));
1099 assert_eq!(colors.accent, Some(Color::Yellow));
1100 }
1101
1102 #[test]
1103 fn align_default_is_start() {
1104 assert_eq!(Align::default(), Align::Start);
1105 }
1106
1107 #[test]
1108 fn justify_default_is_start() {
1109 assert_eq!(Justify::default(), Justify::Start);
1110 }
1111
1112 #[test]
1113 fn align_and_justify_variants_are_distinct() {
1114 assert_ne!(Align::Start, Align::Center);
1115 assert_ne!(Align::Center, Align::End);
1116
1117 assert_ne!(Justify::Start, Justify::Center);
1118 assert_ne!(Justify::Center, Justify::End);
1119 assert_ne!(Justify::SpaceBetween, Justify::SpaceAround);
1120 assert_ne!(Justify::SpaceAround, Justify::SpaceEvenly);
1121 }
1122}