geng_ui/layout_widgets/
stack.rs

1use 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 _};