geng_ui/layout_widgets/
stack.rs1use super::*;
2
3#[derive(Deref, DerefMut)]
4pub struct Stack<'a> {
5 #[deref]
6 #[deref_mut]
7 children: Vec<Box<dyn Widget + 'a>>,
8}
9
10pub fn stack<'a>(widgets: Vec<Box<dyn Widget + 'a>>) -> Stack<'a> {
11 Stack { children: widgets }
12}
13
14#[macro_export]
15macro_rules! stack {
16 ($($x:expr),* $(,)?) => {
17 $crate::stack(vec![$(Box::new($x)),*])
18 };
19}
20
21impl<'a> Widget for Stack<'a> {
22 fn calc_constraints(&mut self, children: &ConstraintsContext) -> Constraints {
23 Constraints {
24 min_size: vec2(
25 self.children
26 .iter()
27 .map(|child| children.get_constraints(child.deref()).min_size.x)
28 .max_by(|a, b| a.partial_cmp(b).unwrap())
29 .unwrap(),
30 self.children
31 .iter()
32 .map(|child| children.get_constraints(child.deref()).min_size.y)
33 .max_by(|a, b| a.partial_cmp(b).unwrap())
34 .unwrap(),
35 ),
36 flex: vec2(
37 self.children
38 .iter()
39 .map(|child| children.get_constraints(child.deref()).flex.x)
40 .max_by(|a, b| a.partial_cmp(b).unwrap())
41 .unwrap(),
42 self.children
43 .iter()
44 .map(|child| children.get_constraints(child.deref()).flex.y)
45 .max_by(|a, b| a.partial_cmp(b).unwrap())
46 .unwrap(),
47 ),
48 }
49 }
50 fn layout_children(&mut self, cx: &mut LayoutContext) {
51 for child in &self.children {
52 cx.set_position(child.deref(), cx.position);
53 }
54 }
55 fn walk_children_mut(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
56 for child in &mut self.children {
57 f(child.deref_mut());
58 }
59 }
60}
61
62mod ext {
63 use super::*;
64
65 pub trait WidgetExt<'a>: Widget + Sized + 'a {
66 fn background_color(self, color: Rgba<f32>) -> Stack<'a> {
67 self.background(ColorBox::new(color))
68 }
69 fn background(self, other: impl Widget + 'a) -> Stack<'a> {
70 stack![other, self]
71 }
72 }
73
74 impl<'a, T: Widget + 'a> WidgetExt<'a> for T {}
75
76 macro_rules! impl_for_tuple {
77 ($($a:ident),*) => {
78 impl<'a, $($a: Widget + 'a),*> TupleExt<'a> for ($($a,)*) {
79 fn stack(self) -> Stack<'a> {
80 let ($($a,)*) = self;
81 super::stack![$($a),*]
82 }
83 }
84 };
85 }
86 call_for_tuples!(impl_for_tuple);
87
88 pub trait TupleExt<'a> {
89 fn stack(self) -> Stack<'a>;
90 }
91}
92
93pub use ext::{TupleExt as _, WidgetExt as _};