1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use super::*;

#[derive(Deref, DerefMut)]
pub struct Stack<'a> {
    #[deref]
    #[deref_mut]
    children: Vec<Box<dyn Widget + 'a>>,
}

pub fn stack<'a>(widgets: Vec<Box<dyn Widget + 'a>>) -> Stack<'a> {
    Stack { children: widgets }
}

#[macro_export]
macro_rules! stack {
    ($($x:expr),* $(,)?) => {
        $crate::stack(vec![$(Box::new($x)),*])
    };
}

impl<'a> Widget for Stack<'a> {
    fn calc_constraints(&mut self, children: &ConstraintsContext) -> Constraints {
        Constraints {
            min_size: vec2(
                self.children
                    .iter()
                    .map(|child| children.get_constraints(child.deref()).min_size.x)
                    .max_by(|a, b| a.partial_cmp(b).unwrap())
                    .unwrap(),
                self.children
                    .iter()
                    .map(|child| children.get_constraints(child.deref()).min_size.y)
                    .max_by(|a, b| a.partial_cmp(b).unwrap())
                    .unwrap(),
            ),
            flex: vec2(
                self.children
                    .iter()
                    .map(|child| children.get_constraints(child.deref()).flex.x)
                    .max_by(|a, b| a.partial_cmp(b).unwrap())
                    .unwrap(),
                self.children
                    .iter()
                    .map(|child| children.get_constraints(child.deref()).flex.y)
                    .max_by(|a, b| a.partial_cmp(b).unwrap())
                    .unwrap(),
            ),
        }
    }
    fn layout_children(&mut self, cx: &mut LayoutContext) {
        for child in &self.children {
            cx.set_position(child.deref(), cx.position);
        }
    }
    fn walk_children_mut(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
        for child in &mut self.children {
            f(child.deref_mut());
        }
    }
}

mod ext {
    use super::*;

    pub trait WidgetExt<'a>: Widget + Sized + 'a {
        fn background_color(self, color: Rgba<f32>) -> Stack<'a> {
            self.background(ColorBox::new(color))
        }
        fn background(self, other: impl Widget + 'a) -> Stack<'a> {
            stack![other, self]
        }
    }

    impl<'a, T: Widget + 'a> WidgetExt<'a> for T {}

    macro_rules! impl_for_tuple {
        ($($a:ident),*) => {
            impl<'a, $($a: Widget + 'a),*> TupleExt<'a> for ($($a,)*) {
                fn stack(self) -> Stack<'a> {
                    let ($($a,)*) = self;
                    super::stack![$($a),*]
                }
            }
        };
    }
    call_for_tuples!(impl_for_tuple);

    pub trait TupleExt<'a> {
        fn stack(self) -> Stack<'a>;
    }
}

pub use ext::{TupleExt as _, WidgetExt as _};