1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4use crate::prelude::{coord, Rect, Shape};
5use crate::ui::layout::LayoutView;
6use crate::ui::PixelView;
7
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9#[derive(Debug, PartialEq, Clone, Copy)]
10pub enum LayoutOffset {
11 Zero,
12 Pixels(isize),
13 Percent(f32),
15}
16
17impl LayoutOffset {
18 pub fn calc(&self, total: usize) -> isize {
19 match self {
20 LayoutOffset::Zero => 0,
21 LayoutOffset::Pixels(px) => *px,
22 LayoutOffset::Percent(percent) => ((total as f32) * percent).round() as isize,
23 }
24 }
25}
26
27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28#[derive(Debug, Clone, PartialEq)]
29pub struct LayoutContext {
30 pub bounds: Rect,
31 pub default_offset: LayoutOffset,
32}
33
34impl LayoutContext {
35 pub fn new(bounds: Rect) -> LayoutContext {
36 LayoutContext {
37 bounds,
38 default_offset: LayoutOffset::Zero,
39 }
40 }
41
42 pub fn new_with_padding(bounds: Rect, padding: usize) -> LayoutContext {
43 LayoutContext {
44 bounds,
45 default_offset: LayoutOffset::Pixels(padding as isize),
46 }
47 }
48}
49
50#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
51pub enum ViewLayoutRule {
52 LeftToLeft,
53 RightToRight,
54 LeftToRight,
55 RightToLeft,
56 TopToTop,
57 BottomToBottom,
58 TopToBottom,
59 BottomToTop,
60 CenterHToLeft,
61 CenterHToRight,
62 CenterHToCenterH,
63 LeftToCenterH,
64 RightToCenterH,
65 CenterVToTop,
66 CenterVToBottom,
67 TopToCenterV,
68 BottomToCenterV,
69 CenterVToCenterV,
70}
71
72#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
73pub enum ParentLayoutRule {
74 FromLeft,
75 FromRight,
76 FromTop,
77 FromBottom,
78 FromCenterH,
79 FromCenterV,
80 FillVert,
81 FillHorz,
82}
83
84trait UpdateRect {
85 fn u_left(&self, value: isize) -> Rect;
86 fn u_top(&self, value: isize) -> Rect;
87 fn u_bottom(&self, value: isize) -> Rect;
88 fn u_right(&self, value: isize) -> Rect;
89 fn u_horz(&self, left: isize, right: isize) -> Rect;
90 fn u_vert(&self, top: isize, bottom: isize) -> Rect;
91}
92
93impl UpdateRect for Rect {
94 fn u_left(&self, value: isize) -> Rect {
95 Rect::new((value, self.top()), self.bottom_right())
96 }
97
98 fn u_top(&self, value: isize) -> Rect {
99 Rect::new((self.left(), value), self.bottom_right())
100 }
101
102 fn u_bottom(&self, value: isize) -> Rect {
103 Rect::new(self.top_left(), (self.right(), value))
104 }
105
106 fn u_right(&self, value: isize) -> Rect {
107 Rect::new(self.top_left(), (value, self.bottom()))
108 }
109
110 fn u_horz(&self, left: isize, right: isize) -> Rect {
111 Rect::new((left, self.top()), (right, self.bottom()))
112 }
113
114 fn u_vert(&self, top: isize, bottom: isize) -> Rect {
115 Rect::new((self.left(), top), (self.right(), bottom))
116 }
117}
118
119pub fn move_by_view(
120 parent: &Rect,
121 view: &mut dyn PixelView,
122 pivot: &dyn PixelView,
123 rule: ViewLayoutRule,
124 offset: LayoutOffset,
125) {
126 match rule {
127 ViewLayoutRule::LeftToLeft => view.set_position(coord!(
128 pivot.bounds().left() + offset.calc(parent.width()),
129 view.bounds().top(),
130 )),
131 ViewLayoutRule::RightToRight => view.set_position(coord!(
132 pivot.bounds().right() + offset.calc(parent.width()) - (view.bounds().width() as isize),
133 view.bounds().top(),
134 )),
135 ViewLayoutRule::LeftToRight => view.set_position(coord!(
136 pivot.bounds().right() + offset.calc(parent.width()),
137 view.bounds().top(),
138 )),
139 ViewLayoutRule::RightToLeft => view.set_position(coord!(
140 pivot.bounds().left() - offset.calc(parent.width()) - (view.bounds().width() as isize),
141 view.bounds().top()
142 )),
143 ViewLayoutRule::TopToTop => view.set_position(coord!(
144 view.bounds().left(),
145 pivot.bounds().top() + offset.calc(parent.height())
146 )),
147 ViewLayoutRule::BottomToBottom => view.set_position(coord!(
148 view.bounds().left(),
149 pivot.bounds().bottom()
150 - offset.calc(parent.height())
151 - (view.bounds().height() as isize)
152 )),
153 ViewLayoutRule::TopToBottom => view.set_position(coord!(
154 view.bounds().left(),
155 pivot.bounds().bottom() + offset.calc(parent.height())
156 )),
157 ViewLayoutRule::BottomToTop => view.set_position(coord!(
158 view.bounds().left(),
159 pivot.bounds().top() - offset.calc(parent.height()) - (view.bounds().height() as isize)
160 )),
161 ViewLayoutRule::CenterHToLeft => view.set_position(coord!(
162 pivot.bounds().left() + offset.calc(parent.width())
163 - (view.bounds().width() as isize / 2),
164 view.bounds().top()
165 )),
166 ViewLayoutRule::CenterHToRight => view.set_position(coord!(
167 pivot.bounds().left()
168 + offset.calc(parent.width())
169 + (view.bounds().width() as isize / 2),
170 view.bounds().top()
171 )),
172 ViewLayoutRule::LeftToCenterH => view.set_position(coord!(
173 pivot.bounds().center().x + offset.calc(parent.width()),
174 view.bounds().top()
175 )),
176 ViewLayoutRule::RightToCenterH => view.set_position(coord!(
177 pivot.bounds().center().x
178 - offset.calc(parent.width())
179 - (view.bounds().width() as isize),
180 view.bounds().top()
181 )),
182 ViewLayoutRule::CenterVToTop => view.set_position(coord!(
183 view.bounds().left(),
184 pivot.bounds().top() + offset.calc(parent.height())
185 - (view.bounds().height() as isize / 2)
186 )),
187 ViewLayoutRule::CenterVToBottom => view.set_position(coord!(
188 view.bounds().left(),
189 pivot.bounds().top()
190 + offset.calc(parent.height())
191 + (view.bounds().height() as isize / 2)
192 )),
193 ViewLayoutRule::TopToCenterV => view.set_position(coord!(
194 view.bounds().left(),
195 pivot.bounds().center().y + offset.calc(parent.height()),
196 )),
197 ViewLayoutRule::BottomToCenterV => view.set_position(coord!(
198 view.bounds().left(),
199 pivot.bounds().center().y + offset.calc(parent.height())
200 - (view.bounds().height() as isize),
201 )),
202 ViewLayoutRule::CenterHToCenterH => view.set_position(coord!(
203 pivot.bounds().center().x + offset.calc(parent.width())
204 - (view.bounds().width() as isize / 2),
205 view.bounds().top()
206 )),
207 ViewLayoutRule::CenterVToCenterV => view.set_position(coord!(
208 view.bounds().left(),
209 pivot.bounds().center().y
210 - offset.calc(parent.height())
211 - (view.bounds().height() as isize / 2),
212 )),
213 }
214}
215
216pub fn center_between(
217 parent: &Rect,
218 view: &mut dyn LayoutView,
219 first: &dyn PixelView,
220 second: &dyn PixelView,
221 horz: bool,
222 offset: LayoutOffset,
223) {
224 if horz {
225 let half_width = (view.bounds().width() / 2) as isize;
226 view.set_position(coord!(
227 first
228 .bounds()
229 .center()
230 .mid_point(second.bounds().center())
231 .x
232 - half_width
233 + offset.calc(parent.width()),
234 view.bounds().top()
235 ));
236 } else {
237 let half_height = (view.bounds().height() / 2) as isize;
238 view.set_position(coord!(
239 view.bounds().left(),
240 first
241 .bounds()
242 .center()
243 .mid_point(second.bounds().center())
244 .y
245 - half_height
246 + offset.calc(parent.height())
247 ));
248 }
249}
250
251pub fn grow_by_view(
252 parent: &Rect,
253 view: &mut dyn LayoutView,
254 pivot: &dyn PixelView,
255 rule: ViewLayoutRule,
256 offset: LayoutOffset,
257) {
258 match rule {
259 ViewLayoutRule::LeftToLeft => view.set_bounds(
260 view.bounds()
261 .u_left(pivot.bounds().left() + offset.calc(parent.width())),
262 ),
263 ViewLayoutRule::RightToRight => view.set_bounds(
264 view.bounds()
265 .u_right(pivot.bounds().right() - offset.calc(parent.width())),
266 ),
267 ViewLayoutRule::LeftToRight => view.set_bounds(
268 view.bounds()
269 .u_left(pivot.bounds().right() + offset.calc(parent.width())),
270 ),
271 ViewLayoutRule::RightToLeft => view.set_bounds(
272 view.bounds()
273 .u_right(pivot.bounds().left() - offset.calc(parent.width())),
274 ),
275 ViewLayoutRule::TopToTop => view.set_bounds(
276 view.bounds()
277 .u_top(pivot.bounds().top() + offset.calc(parent.height())),
278 ),
279 ViewLayoutRule::BottomToBottom => view.set_bounds(
280 view.bounds()
281 .u_bottom(pivot.bounds().bottom() - offset.calc(parent.height())),
282 ),
283 ViewLayoutRule::TopToBottom => view.set_bounds(
284 view.bounds()
285 .u_top(pivot.bounds().bottom() + offset.calc(parent.height())),
286 ),
287 ViewLayoutRule::BottomToTop => view.set_bounds(
288 view.bounds()
289 .u_bottom(pivot.bounds().top() - offset.calc(parent.height())),
290 ),
291 ViewLayoutRule::LeftToCenterH => view.set_bounds(
292 view.bounds()
293 .u_left(pivot.bounds().center().x + offset.calc(parent.width())),
294 ),
295 ViewLayoutRule::RightToCenterH => view.set_bounds(
296 view.bounds()
297 .u_right(pivot.bounds().center().x + offset.calc(parent.width())),
298 ),
299 ViewLayoutRule::TopToCenterV => view.set_bounds(
300 view.bounds()
301 .u_top(pivot.bounds().center().y + offset.calc(parent.width())),
302 ),
303 ViewLayoutRule::BottomToCenterV => view.set_bounds(
304 view.bounds()
305 .u_bottom(pivot.bounds().center().y + offset.calc(parent.width())),
306 ),
307 _ => {}
308 }
309}
310
311pub fn move_by_parent(
312 parent: &Rect,
313 view: &mut dyn PixelView,
314 rule: ParentLayoutRule,
315 offset: LayoutOffset,
316) {
317 match rule {
318 ParentLayoutRule::FromLeft => view.set_position(coord!(
319 parent.left() + offset.calc(parent.width()),
320 view.bounds().top(),
321 )),
322 ParentLayoutRule::FromRight => view.set_position(coord!(
323 parent.right() - (view.bounds().width() as isize) - offset.calc(parent.width()),
324 view.bounds().top(),
325 )),
326 ParentLayoutRule::FromTop => view.set_position(coord!(
327 view.bounds().left(),
328 parent.top() + offset.calc(parent.height()),
329 )),
330 ParentLayoutRule::FromBottom => view.set_position(coord!(
331 view.bounds().left(),
332 parent.bottom() - (view.bounds().height() as isize) - offset.calc(parent.height()),
333 )),
334 ParentLayoutRule::FromCenterH => view.set_position(coord!(
335 parent.center().x + offset.calc(parent.width()) - (view.bounds().width() as isize / 2),
336 view.bounds().top(),
337 )),
338 ParentLayoutRule::FromCenterV => view.set_position(coord!(
339 view.bounds().left(),
340 parent.center().y + offset.calc(parent.height())
341 - (view.bounds().height() as isize / 2),
342 )),
343 _ => {}
344 }
345}
346
347pub fn grow_by_parent(
348 parent: &Rect,
349 view: &mut dyn LayoutView,
350 rule: ParentLayoutRule,
351 offset: LayoutOffset,
352) {
353 match rule {
354 ParentLayoutRule::FromLeft => view.set_bounds(
355 view.bounds()
356 .u_left(parent.left() + offset.calc(parent.width())),
357 ),
358 ParentLayoutRule::FromRight => view.set_bounds(
359 view.bounds()
360 .u_right(parent.right() - offset.calc(parent.width())),
361 ),
362 ParentLayoutRule::FromTop => view.set_bounds(
363 view.bounds()
364 .u_top(parent.top() + offset.calc(parent.height())),
365 ),
366 ParentLayoutRule::FromBottom => view.set_bounds(
367 view.bounds()
368 .u_bottom(parent.bottom() - offset.calc(parent.height())),
369 ),
370 ParentLayoutRule::FillVert => view.set_bounds(view.bounds().u_vert(
371 parent.top() + offset.calc(parent.height()),
372 parent.bottom() - offset.calc(parent.height()),
373 )),
374 ParentLayoutRule::FillHorz => view.set_bounds(view.bounds().u_horz(
375 parent.left() + offset.calc(parent.width()),
376 parent.right() - offset.calc(parent.width()),
377 )),
378 ParentLayoutRule::FromCenterH => {
379 if view.bounds().center().x < parent.center().x {
380 view.set_bounds(
381 view.bounds()
382 .u_right(parent.center().x + offset.calc(parent.width())),
383 )
384 } else {
385 view.set_bounds(
386 view.bounds()
387 .u_left(parent.center().x - offset.calc(parent.width())),
388 )
389 }
390 }
391 ParentLayoutRule::FromCenterV => {
392 if view.bounds().center().y < parent.center().y {
393 view.set_bounds(
394 view.bounds()
395 .u_bottom(parent.center().y + offset.calc(parent.height())),
396 )
397 } else {
398 view.set_bounds(
399 view.bounds()
400 .u_top(parent.center().y - offset.calc(parent.height())),
401 )
402 }
403 }
404 }
405}
406
407#[macro_export]
480macro_rules! layout {
481 ($context:expr, $view:expr, left_to_left_of $pivot:expr $(, $offset:expr)?) => {
482 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToLeft, $crate::or_else!($($offset)?, $context.default_offset));
483 };
484 ($context:expr, $view:expr, left_to_right_of $pivot:expr $(, $offset:expr)?) => {
485 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToRight, $crate::or_else!($($offset)?, $context.default_offset));
486 };
487 ($context:expr, $view:expr, right_to_left_of $pivot:expr $(, $offset:expr)?) => {
488 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToLeft, $crate::or_else!($($offset)?, $context.default_offset));
489 };
490 ($context:expr, $view:expr, top_to_bottom_of $pivot:expr $(, $offset:expr)?) => {
491 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToBottom, $crate::or_else!($($offset)?, $context.default_offset));
492 };
493 ($context:expr, $view:expr, bottom_to_top_of $pivot:expr $(, $offset:expr)?) => {
494 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToTop, $crate::or_else!($($offset)?, $context.default_offset));
495 };
496 ($context:expr, $view:expr, top_to_top_of $pivot:expr $(, $offset:expr)?) => {
497 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToTop, $crate::or_else!($($offset)?, $context.default_offset));
498 };
499 ($context:expr, $view:expr, bottom_to_bottom_of $pivot:expr $(, $offset:expr)?) => {
500 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToBottom, $crate::or_else!($($offset)?, $context.default_offset));
501 };
502 ($context:expr, $view:expr, right_to_right_of $pivot:expr $(, $offset:expr)?) => {
503 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToRight, $crate::or_else!($($offset)?, $context.default_offset));
504 };
505 ($context:expr, grow $view:expr, right_to_right_of $pivot:expr $(, $offset:expr)?) => {
506 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToRight, $crate::or_else!($($offset)?, $context.default_offset));
507 };
508 ($context:expr, grow $view:expr, right_to_left_of $pivot:expr $(, $offset:expr)?) => {
509 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToLeft, $crate::or_else!($($offset)?, $context.default_offset));
510 };
511 ($context:expr, grow $view:expr, bottom_to_bottom_of $pivot:expr $(, $offset:expr)?) => {
512 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToBottom, $crate::or_else!($($offset)?, $context.default_offset));
513 };
514 ($context:expr, grow $view:expr, bottom_to_top_of $pivot:expr $(, $offset:expr)?) => {
515 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToTop, $crate::or_else!($($offset)?, $context.default_offset));
516 };
517 ($context:expr, grow $view:expr, left_to_left_of $pivot:expr $(, $offset:expr)?) => {
518 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToLeft, $crate::or_else!($($offset)?, $context.default_offset));
519 };
520 ($context:expr, grow $view:expr, left_to_right_of $pivot:expr $(, $offset:expr)?) => {
521 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToRight, $crate::or_else!($($offset)?, $context.default_offset));
522 };
523 ($context:expr, grow $view:expr, top_to_top_of $pivot:expr $(, $offset:expr)?) => {
524 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToTop, $crate::or_else!($($offset)?, $context.default_offset));
525 };
526 ($context:expr, $view:expr, centerh_to_centerh_of $pivot:expr $(, $offset:expr)?) => {
527 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterHToCenterH, $crate::or_else!($($offset)?, $context.default_offset));
528 };
529 ($context:expr, $view:expr, centerh_to_left_of $pivot:expr $(, $offset:expr)?) => {
530 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterHToLeft, $crate::or_else!($($offset)?, $context.default_offset));
531 };
532 ($context:expr, $view:expr, centerh_to_right_of $pivot:expr $(, $offset:expr)?) => {
533 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterHToRight, $crate::or_else!($($offset)?, $context.default_offset));
534 };
535 ($context:expr, $view:expr, centerv_to_centerv_of $pivot:expr $(, $offset:expr)?) => {
536 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterVToCenterV, $crate::or_else!($($offset)?, $context.default_offset));
537 };
538 ($context:expr, $view:expr, centerv_to_top_of $pivot:expr $(, $offset:expr)?) => {
539 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterVToTop, $crate::or_else!($($offset)?, $context.default_offset));
540 };
541 ($context:expr, $view:expr, centerv_to_bottom_of $pivot:expr $(, $offset:expr)?) => {
542 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::CenterVToBottom, $crate::or_else!($($offset)?, $context.default_offset));
543 };
544 ($context:expr, $view:expr, left_to_centerh_of $pivot:expr $(, $offset:expr)?) => {
545 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToCenterH, $crate::or_else!($($offset)?, $context.default_offset));
546 };
547 ($context:expr, $view:expr, right_to_centerh_of $pivot:expr $(, $offset:expr)?) => {
548 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToCenterH, $crate::or_else!($($offset)?, $context.default_offset));
549 };
550 ($context:expr, grow $view:expr, left_to_centerh_of $pivot:expr $(, $offset:expr)?) => {
551 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::LeftToCenterH, $crate::or_else!($($offset)?, $context.default_offset));
552 };
553 ($context:expr, grow $view:expr, right_to_centerh_of $pivot:expr $(, $offset:expr)?) => {
554 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::RightToCenterH, $crate::or_else!($($offset)?, $context.default_offset));
555 };
556 ($context:expr, $view:expr, top_to_centerv_of $pivot:expr $(, $offset:expr)?) => {
557 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToCenterV, $crate::or_else!($($offset)?, $context.default_offset));
558 };
559 ($context:expr, $view:expr, bottom_to_centerv_of $pivot:expr $(, $offset:expr)?) => {
560 $crate::ui::layout::relative::move_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToCenterV, $crate::or_else!($($offset)?, $context.default_offset));
561 };
562 ($context:expr, grow $view:expr, top_to_centerv_of $pivot:expr $(, $offset:expr)?) => {
563 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToCenterV, $crate::or_else!($($offset)?, $context.default_offset));
564 };
565 ($context:expr, grow $view:expr, bottom_to_centerv_of $pivot:expr $(, $offset:expr)?) => {
566 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::BottomToCenterV, $crate::or_else!($($offset)?, $context.default_offset));
567 };
568 ($context:expr, grow $view:expr, top_to_bottom_of $pivot:expr $(, $offset:expr)?) => {
569 $crate::ui::layout::relative::grow_by_view(&$context.bounds, &mut $view, &$pivot, $crate::ui::layout::relative::ViewLayoutRule::TopToBottom, $crate::or_else!($($offset)?, $context.default_offset));
570 };
571 ($context:expr, grow $view:expr, fill_width $(, $offset:expr)?) => {
572 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FillHorz, $crate::or_else!($($offset)?, $context.default_offset));
573 };
574 ($context:expr, grow $view:expr, fill_height $(, $offset:expr)?) => {
575 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FillVert, $crate::or_else!($($offset)?, $context.default_offset));
576 };
577 ($context:expr, grow $view:expr, align_left $(, $offset:expr)?) => {
578 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromLeft, $crate::or_else!($($offset)?, $context.default_offset));
579 };
580 ($context:expr, grow $view:expr, align_top $(, $offset:expr)?) => {
581 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromTop, $crate::or_else!($($offset)?, $context.default_offset));
582 };
583 ($context:expr, grow $view:expr, align_right $(, $offset:expr)?) => {
584 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromRight, $crate::or_else!($($offset)?, $context.default_offset));
585 };
586 ($context:expr, grow $view:expr, align_bottom $(, $offset:expr)?) => {
587 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromBottom, $crate::or_else!($($offset)?, $context.default_offset));
588 };
589 ($context:expr, $view:expr, align_left $(, $offset:expr)?) => {
590 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromLeft, $crate::or_else!($($offset)?, $context.default_offset));
591 };
592 ($context:expr, $view:expr, align_top $(, $offset:expr)?) => {
593 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromTop, $crate::or_else!($($offset)?, $context.default_offset));
594 };
595 ($context:expr, $view:expr, align_right $(, $offset:expr)?) => {
596 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromRight, $crate::or_else!($($offset)?, $context.default_offset));
597 };
598 ($context:expr, $view:expr, align_bottom $(, $offset:expr)?) => {
599 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromBottom, $crate::or_else!($($offset)?, $context.default_offset));
600 };
601 ($context:expr, $view:expr, align_centerh $(, $offset:expr)?) => {
602 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromCenterH, $crate::or_else!($($offset)?, $context.default_offset));
603 };
604 ($context:expr, $view:expr, align_centerv $(, $offset:expr)?) => {
605 $crate::ui::layout::relative::move_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromCenterV, $crate::or_else!($($offset)?, $context.default_offset));
606 };
607 ($context:expr, grow $view:expr, align_centerh $(, $offset:expr)?) => {
608 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromCenterH, $crate::or_else!($($offset)?, $context.default_offset));
609 };
610 ($context:expr, grow $view:expr, align_centerv $(, $offset:expr)?) => {
611 $crate::ui::layout::relative::grow_by_parent(&$context.bounds, &mut $view, $crate::ui::layout::relative::ParentLayoutRule::FromCenterV, $crate::or_else!($($offset)?, $context.default_offset));
612 };
613 ($context:expr, centerh $view:expr, between $first:expr, $second:expr $(, $offset:expr)?) => {
614 $crate::ui::layout::relative::center_between(&$context.bounds, &mut $view, &$first, &$second, true, $context.default_offset);
615 };
616 ($context:expr, centerv $view:expr, between $first:expr, $second:expr $(, $offset:expr)?) => {
617 $crate::ui::layout::relative::center_between(&$context.bounds, &mut $view, &$first, &$second, false, $context.default_offset);
618 };
619}
620
621#[macro_export]
622macro_rules! px {
623 ($number:expr) => {
624 $crate::ui::layout::relative::LayoutOffset::Pixels($number)
625 };
626}
627
628#[macro_export]
629macro_rules! parent {
630 ($number:expr) => {
631 $crate::ui::layout::relative::LayoutOffset::Percent($number)
632 };
633}