embedded_layout/layout/linear/
secondary_alignment.rs

1use embedded_graphics::prelude::Size;
2
3use crate::{align::Alignment, prelude::*};
4
5/// Secondary alignment is used to align views perpendicular to the placement axis.
6///
7/// For example, use [`horizontal::Right`] to align views to the right in a vertical linear layout.
8///
9/// `SecondaryAlignment` should be implemented by custom `Alignment` types, otherwise they won't be
10/// compatible with [`LinearLayout`].
11///
12/// [`LinearLayout`]: crate::layout::linear::LinearLayout
13pub trait SecondaryAlignment: Alignment {
14    /// The secondary alignment of the first view
15    type First: Alignment;
16
17    /// Return the combined `Size` occupied by both `Views` after they are arranged.
18    ///
19    /// I.e. [`horizontal::Left`] returns the maximum width, while [`horizontal::LeftToRight`]
20    /// returns the sum of the two widths.
21    fn measure(prev: Size, view_size: Size) -> Size;
22}
23
24fn max_width(prev_size: Size, view_size: Size) -> Size {
25    Size::new(
26        prev_size.width.max(view_size.width),
27        prev_size.height + view_size.height,
28    )
29}
30
31const fn cascading(prev_size: Size, view_size: Size) -> Size {
32    Size::new(
33        prev_size.width + view_size.width,
34        prev_size.height + view_size.height,
35    )
36}
37
38impl SecondaryAlignment for horizontal::Left {
39    type First = horizontal::Left;
40
41    #[inline]
42    fn measure(prev_size: Size, view_size: Size) -> Size {
43        max_width(prev_size, view_size)
44    }
45}
46
47impl SecondaryAlignment for horizontal::Center {
48    type First = horizontal::Center;
49
50    #[inline]
51    fn measure(prev_size: Size, view_size: Size) -> Size {
52        max_width(prev_size, view_size)
53    }
54}
55
56impl SecondaryAlignment for horizontal::Right {
57    type First = horizontal::Right;
58
59    #[inline]
60    fn measure(prev_size: Size, view_size: Size) -> Size {
61        max_width(prev_size, view_size)
62    }
63}
64
65impl SecondaryAlignment for horizontal::RightToLeft {
66    type First = horizontal::Right;
67
68    #[inline]
69    fn measure(prev_size: Size, view_size: Size) -> Size {
70        cascading(prev_size, view_size)
71    }
72}
73
74impl SecondaryAlignment for horizontal::LeftToRight {
75    type First = horizontal::Left;
76
77    #[inline]
78    fn measure(prev_size: Size, view_size: Size) -> Size {
79        cascading(prev_size, view_size)
80    }
81}
82
83fn max_height(prev_size: Size, view_size: Size) -> Size {
84    Size::new(
85        prev_size.width + view_size.width,
86        prev_size.height.max(view_size.height),
87    )
88}
89
90impl SecondaryAlignment for vertical::Top {
91    type First = vertical::Top;
92
93    #[inline]
94    fn measure(prev_size: Size, view_size: Size) -> Size {
95        max_height(prev_size, view_size)
96    }
97}
98
99impl SecondaryAlignment for vertical::Center {
100    type First = vertical::Center;
101
102    #[inline]
103    fn measure(prev_size: Size, view_size: Size) -> Size {
104        max_height(prev_size, view_size)
105    }
106}
107
108impl SecondaryAlignment for vertical::Bottom {
109    type First = vertical::Bottom;
110
111    #[inline]
112    fn measure(prev_size: Size, view_size: Size) -> Size {
113        max_height(prev_size, view_size)
114    }
115}
116
117impl SecondaryAlignment for vertical::TopToBottom {
118    type First = vertical::Top;
119
120    #[inline]
121    fn measure(prev_size: Size, view_size: Size) -> Size {
122        cascading(prev_size, view_size)
123    }
124}
125
126impl SecondaryAlignment for vertical::BottomToTop {
127    type First = vertical::Bottom;
128
129    #[inline]
130    fn measure(prev_size: Size, view_size: Size) -> Size {
131        cascading(prev_size, view_size)
132    }
133}