embedded_layout/align/horizontal/
mod.rs1use crate::align::{Alignment, HorizontalAlignment};
5use embedded_graphics::{geometry::AnchorPoint, primitives::Rectangle};
6
7#[derive(Copy, Clone, Default)]
9pub struct NoAlignment;
10impl HorizontalAlignment for NoAlignment {}
11
12impl Alignment for NoAlignment {
13 #[inline]
14 fn align_with_offset(&self, _object: Rectangle, _reference: Rectangle, _offset: i32) -> i32 {
15 0
16 }
17}
18
19#[derive(Copy, Clone, Default)]
24pub struct Center;
25impl HorizontalAlignment for Center {}
26
27impl Alignment for Center {
28 #[inline]
29 fn align_with_offset(&self, object: Rectangle, reference: Rectangle, offset: i32) -> i32 {
30 reference.anchor_point(AnchorPoint::Center).x - object.anchor_point(AnchorPoint::Center).x
31 + offset
32 }
33}
34
35#[derive(Copy, Clone, Default)]
37pub struct Left;
38impl HorizontalAlignment for Left {}
39
40impl Alignment for Left {
41 #[inline]
42 fn align_with_offset(&self, object: Rectangle, reference: Rectangle, offset: i32) -> i32 {
43 reference.top_left.x - object.top_left.x + offset
44 }
45}
46
47#[derive(Copy, Clone, Default)]
49pub struct Right;
50impl HorizontalAlignment for Right {}
51
52impl Alignment for Right {
53 #[inline]
54 fn align_with_offset(&self, object: Rectangle, reference: Rectangle, offset: i32) -> i32 {
55 reference.anchor_point(AnchorPoint::BottomRight).x
56 - object.anchor_point(AnchorPoint::BottomRight).x
57 + offset
58 }
59}
60
61#[derive(Copy, Clone, Default)]
63pub struct LeftToRight;
64impl HorizontalAlignment for LeftToRight {}
65
66impl Alignment for LeftToRight {
67 #[inline]
68 fn align_with_offset(&self, object: Rectangle, reference: Rectangle, offset: i32) -> i32 {
69 let offset = if object.size.width == 0 {
70 offset
71 } else {
72 offset + 1
73 };
74 reference.anchor_point(AnchorPoint::BottomRight).x - object.top_left.x + offset
75 }
76}
77
78#[derive(Copy, Clone, Default)]
80pub struct RightToLeft;
81impl HorizontalAlignment for RightToLeft {}
82
83impl Alignment for RightToLeft {
84 #[inline]
85 fn align_with_offset(&self, object: Rectangle, reference: Rectangle, offset: i32) -> i32 {
86 let offset = if object.size.width == 0 {
87 offset
88 } else {
89 offset - 1
90 };
91 reference.top_left.x - object.anchor_point(AnchorPoint::BottomRight).x + offset
92 }
93}
94
95#[cfg(test)]
96mod test {
97 use crate::prelude::*;
98 use embedded_graphics::{
99 geometry::{AnchorPoint, Point},
100 prelude::Size,
101 primitives::Rectangle,
102 };
103
104 #[test]
105 fn test_center() {
106 fn check_center_alignment(source: Rectangle, reference: Rectangle, result: Rectangle) {
107 let center_of_reference = reference.top_left + reference.size() / 2;
108 let center_of_result = result.top_left + result.size() / 2;
109
110 assert_eq!(result.size(), source.size());
112
113 assert_eq!(center_of_result.x, center_of_reference.x);
115
116 assert_eq!(result.top_left.y, source.top_left.y);
118 }
119
120 let rect1 = Rectangle::with_corners(Point::new(0, 0), Point::new(10, 10));
121 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
122
123 let result = rect1.align_to(&rect2, horizontal::Center, vertical::NoAlignment);
124 check_center_alignment(rect1, rect2, result);
125
126 let result = rect2.align_to(&rect1, horizontal::Center, vertical::NoAlignment);
128 check_center_alignment(rect2, rect1, result);
129 }
130
131 #[test]
132 fn test_left() {
133 fn check_left_alignment(source: Rectangle, reference: Rectangle, result: Rectangle) {
134 assert_eq!(result.size(), source.size());
136
137 assert_eq!(result.top_left.x, reference.top_left.x);
139
140 assert_eq!(result.top_left.y, source.top_left.y);
142 }
143
144 let rect1 = Rectangle::with_corners(Point::new(0, 0), Point::new(10, 10));
145 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
146
147 let result = rect1.align_to(&rect2, horizontal::Left, vertical::NoAlignment);
148 check_left_alignment(rect1, rect2, result);
149
150 let result = rect2.align_to(&rect1, horizontal::Left, vertical::NoAlignment);
152 check_left_alignment(rect2, rect1, result);
153 }
154
155 #[test]
156 fn test_right() {
157 fn check_right_alignment(source: Rectangle, reference: Rectangle, result: Rectangle) {
158 assert_eq!(result.size(), source.size());
160
161 assert_eq!(
163 result.anchor_point(AnchorPoint::BottomRight).x,
164 reference.anchor_point(AnchorPoint::BottomRight).x
165 );
166
167 assert_eq!(
169 result.anchor_point(AnchorPoint::BottomRight).y,
170 source.anchor_point(AnchorPoint::BottomRight).y
171 );
172 }
173
174 let rect1 = Rectangle::with_corners(Point::new(0, 0), Point::new(10, 10));
175 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
176
177 let result = rect1.align_to(&rect2, horizontal::Right, vertical::NoAlignment);
178 check_right_alignment(rect1, rect2, result);
179
180 let result = rect2.align_to(&rect1, horizontal::Right, vertical::NoAlignment);
182 check_right_alignment(rect2, rect1, result);
183 }
184
185 #[test]
186 fn test_left_to_right() {
187 fn check_left_to_right_alignment(
188 source: Rectangle,
189 reference: Rectangle,
190 result: Rectangle,
191 ) {
192 assert_eq!(result.size(), source.size());
194
195 assert_eq!(
197 result.top_left.x,
198 reference.anchor_point(AnchorPoint::BottomRight).x + 1
199 );
200
201 assert_eq!(
203 result.anchor_point(AnchorPoint::BottomRight).y,
204 source.anchor_point(AnchorPoint::BottomRight).y
205 );
206 }
207
208 let rect1 = Rectangle::with_corners(Point::new(0, 0), Point::new(10, 10));
209 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
210
211 let result = rect1.align_to(&rect2, horizontal::LeftToRight, vertical::NoAlignment);
212 check_left_to_right_alignment(rect1, rect2, result);
213
214 let result = rect2.align_to(&rect1, horizontal::LeftToRight, vertical::NoAlignment);
216 check_left_to_right_alignment(rect2, rect1, result);
217 }
218
219 #[test]
220 fn test_left_to_right_empty() {
221 let rect1 = Rectangle::new(Point::new(0, 0), Size::zero());
222 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
223
224 let result = rect1.align_to(&rect2, horizontal::LeftToRight, vertical::NoAlignment);
225 assert_eq!(result.size(), rect1.size());
227
228 assert_eq!(
230 result.top_left.x,
231 rect2.anchor_point(AnchorPoint::BottomRight).x
232 );
233
234 assert_eq!(
236 result.anchor_point(AnchorPoint::BottomRight).y,
237 rect1.anchor_point(AnchorPoint::BottomRight).y
238 );
239
240 let result = rect2.align_to(&rect1, horizontal::LeftToRight, vertical::NoAlignment);
242
243 assert_eq!(result.size(), rect2.size());
245
246 assert_eq!(
248 result.top_left.x,
249 rect1.anchor_point(AnchorPoint::BottomRight).x + 1
250 );
251
252 assert_eq!(
254 result.anchor_point(AnchorPoint::BottomRight).y,
255 rect2.anchor_point(AnchorPoint::BottomRight).y
256 );
257 }
258
259 #[test]
260 fn test_right_to_left() {
261 let rect1 = Rectangle::with_corners(Point::new(0, 0), Point::new(10, 10));
262 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
263
264 let result = rect1.align_to(&rect2, horizontal::RightToLeft, vertical::NoAlignment);
265 assert_eq!(result.size(), rect1.size());
267
268 assert_eq!(
270 result.anchor_point(AnchorPoint::BottomRight).x,
271 rect2.top_left.x - 1
272 );
273
274 assert_eq!(
276 result.anchor_point(AnchorPoint::BottomRight).y,
277 rect1.anchor_point(AnchorPoint::BottomRight).y
278 );
279
280 let result = rect2.align_to(&rect1, horizontal::RightToLeft, vertical::NoAlignment);
282 assert_eq!(result.size(), rect2.size());
284
285 assert_eq!(
287 result.anchor_point(AnchorPoint::BottomRight).x,
288 rect1.top_left.x - 1
289 );
290
291 assert_eq!(
293 result.anchor_point(AnchorPoint::BottomRight).y,
294 rect2.anchor_point(AnchorPoint::BottomRight).y
295 );
296 }
297
298 #[test]
299 fn test_right_to_left_empty() {
300 let rect1 = Rectangle::new(Point::new(0, 0), Size::zero());
301 let rect2 = Rectangle::with_corners(Point::new(30, 20), Point::new(40, 50));
302
303 let result = rect1.align_to(&rect2, horizontal::RightToLeft, vertical::NoAlignment);
304 assert_eq!(result.size(), rect1.size());
306
307 assert_eq!(
309 result.anchor_point(AnchorPoint::BottomRight).x,
310 rect2.top_left.x
311 );
312
313 assert_eq!(
315 result.anchor_point(AnchorPoint::BottomRight).y,
316 rect1.anchor_point(AnchorPoint::BottomRight).y
317 );
318
319 let result = rect2.align_to(&rect1, horizontal::RightToLeft, vertical::NoAlignment);
321 assert_eq!(result.size(), rect2.size());
323
324 assert_eq!(
326 result.anchor_point(AnchorPoint::BottomRight).x,
327 rect1.top_left.x - 1
328 );
329
330 assert_eq!(
332 result.anchor_point(AnchorPoint::BottomRight).y,
333 rect2.anchor_point(AnchorPoint::BottomRight).y
334 );
335 }
336}