embedded_layout/layout/linear/
orientation.rs1use crate::{
2 align::{horizontal, vertical, Alignment, HorizontalAlignment, VerticalAlignment},
3 layout::linear::{
4 secondary_alignment::SecondaryAlignment,
5 spacing::{ElementSpacing, Tight},
6 },
7 View,
8};
9use embedded_graphics::{
10 prelude::{Point, Size},
11 primitives::Rectangle,
12};
13
14pub trait Orientation: Copy + Clone {
16 type Secondary: SecondaryAlignment + Alignment;
18
19 fn destructure_size(size: Size) -> (u32, u32);
21
22 fn create_size(primary: u32, secondary: u32) -> Size;
24
25 fn compute_offset(
27 &self,
28 bounds: Rectangle,
29 size: Size,
30 previous: Rectangle,
31 n: usize,
32 count: usize,
33 ) -> Point;
34
35 #[inline]
37 fn place(
38 &self,
39 view: &mut dyn View,
40 size: Size,
41 previous: Rectangle,
42 n: usize,
43 count: usize,
44 ) -> Rectangle {
45 let offset = self.compute_offset(view.bounds(), size, previous, n, count);
46 view.translate_impl(offset);
47 view.bounds()
48 }
49}
50
51#[derive(Copy, Clone)]
53pub struct Horizontal<Secondary, Spacing = Tight>
54where
55 Secondary: SecondaryAlignment + VerticalAlignment,
56 Spacing: ElementSpacing,
57{
58 pub(crate) secondary: Secondary,
59 pub(crate) spacing: Spacing,
60}
61
62impl<Secondary, Spacing> Horizontal<Secondary, Spacing>
63where
64 Secondary: SecondaryAlignment + VerticalAlignment,
65 Spacing: ElementSpacing,
66{
67 #[inline]
69 pub fn with_secondary_alignment<Sec: SecondaryAlignment + VerticalAlignment>(
70 self,
71 secondary: Sec,
72 ) -> Horizontal<Sec, Spacing> {
73 Horizontal {
74 secondary,
75 spacing: self.spacing,
76 }
77 }
78
79 #[inline]
81 pub fn with_spacing<ElSpacing: ElementSpacing>(
82 self,
83 spacing: ElSpacing,
84 ) -> Horizontal<Secondary, ElSpacing> {
85 Horizontal {
86 secondary: self.secondary,
87 spacing,
88 }
89 }
90}
91
92impl Default for Horizontal<vertical::Bottom, Tight> {
93 #[inline]
94 fn default() -> Self {
95 Self {
96 secondary: vertical::Bottom,
97 spacing: Tight,
98 }
99 }
100}
101
102impl<Secondary, Spacing> Orientation for Horizontal<Secondary, Spacing>
103where
104 Secondary: SecondaryAlignment + VerticalAlignment,
105 Spacing: ElementSpacing,
106{
107 type Secondary = Secondary;
108
109 #[inline]
110 fn destructure_size(size: Size) -> (u32, u32) {
111 (size.width, size.height)
112 }
113
114 #[inline]
115 fn create_size(primary: u32, secondary: u32) -> Size {
116 Size::new(primary, secondary)
117 }
118
119 #[inline]
120 fn compute_offset(
121 &self,
122 bounds: Rectangle,
123 size: Size,
124 previous: Rectangle,
125 n: usize,
126 count: usize,
127 ) -> Point {
128 let (primary_size, _) = Self::destructure_size(size);
129
130 if n == 0 {
131 Point::new(
132 self.spacing
133 .align(horizontal::Left, bounds, previous, n, count, primary_size),
134 Secondary::First::default().align(bounds, previous),
135 )
136 } else {
137 Point::new(
138 self.spacing.align(
139 horizontal::LeftToRight,
140 bounds,
141 previous,
142 n,
143 count,
144 primary_size,
145 ),
146 Secondary::default().align(bounds, previous),
147 )
148 }
149 }
150}
151
152#[derive(Copy, Clone)]
154pub struct Vertical<Secondary, Spacing = Tight>
155where
156 Secondary: SecondaryAlignment + HorizontalAlignment,
157 Spacing: ElementSpacing,
158{
159 pub(crate) secondary: Secondary,
160 pub(crate) spacing: Spacing,
161}
162
163impl Default for Vertical<horizontal::Left, Tight> {
164 #[inline]
165 fn default() -> Self {
166 Self {
167 secondary: horizontal::Left,
168 spacing: Tight,
169 }
170 }
171}
172
173impl<Secondary, Spacing> Vertical<Secondary, Spacing>
174where
175 Secondary: SecondaryAlignment + HorizontalAlignment,
176 Spacing: ElementSpacing,
177{
178 #[inline]
180 pub fn with_secondary_alignment<Sec: SecondaryAlignment + HorizontalAlignment>(
181 self,
182 secondary: Sec,
183 ) -> Vertical<Sec, Spacing> {
184 Vertical {
185 secondary,
186 spacing: self.spacing,
187 }
188 }
189
190 #[inline]
192 pub fn with_spacing<ElSpacing: ElementSpacing>(
193 self,
194 spacing: ElSpacing,
195 ) -> Vertical<Secondary, ElSpacing> {
196 Vertical {
197 secondary: self.secondary,
198 spacing,
199 }
200 }
201}
202
203impl<Secondary, Spacing> Orientation for Vertical<Secondary, Spacing>
204where
205 Secondary: SecondaryAlignment + HorizontalAlignment,
206 Spacing: ElementSpacing,
207{
208 type Secondary = Secondary;
209
210 #[inline]
211 fn destructure_size(size: Size) -> (u32, u32) {
212 (size.height, size.width)
213 }
214
215 #[inline]
216 fn create_size(primary: u32, secondary: u32) -> Size {
217 Size::new(secondary, primary)
218 }
219
220 #[inline]
221 fn compute_offset(
222 &self,
223 bounds: Rectangle,
224 size: Size,
225 previous: Rectangle,
226 n: usize,
227 count: usize,
228 ) -> Point {
229 let (primary_size, _) = Self::destructure_size(size);
230
231 if n == 0 {
232 Point::new(
233 Secondary::First::default().align(bounds, previous),
234 self.spacing
235 .align(vertical::Top, bounds, previous, n, count, primary_size),
236 )
237 } else {
238 Point::new(
239 Secondary::default().align(bounds, previous),
240 self.spacing.align(
241 vertical::TopToBottom,
242 bounds,
243 previous,
244 n,
245 count,
246 primary_size,
247 ),
248 )
249 }
250 }
251}