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
mod button;
mod h_stack;
mod text_field;
mod text;
mod v_stack;
mod z_stack;

pub use button::*;
pub use h_stack::*;
pub use text_field::*;
pub use text::*;
pub use v_stack::*;
pub use z_stack::*;

use crate::{Primitive, Bind, Context, Id};

/// The primary view trait. Represents a lightweight UI component.
pub trait View: Bind {
    type Body: View = !;

    fn body(&self) -> Self::Body {
        panic!("View does not have a body!")
    }

    fn render(&mut self, context: &Context) -> Id<Primitive> {
        self.bind(context);
        self.body().render(context)
    }
}

// TODO: Generate tuple variants with a macro (or variadic generics once possible)

impl View for ! {}

impl View for () {
    fn render(&mut self, context: &Context) -> Id<Primitive> {
        context.identify(Primitive::Empty)
    }
}

impl<T> View for (T,) where T: View {
    type Body = T::Body;

    fn body(&self) -> Self::Body {
        self.0.body()
    }

    fn render(&mut self, context: &Context) -> Id<Primitive> {
        self.0.render(&context.child(0))
    }
}

impl<T, U> View for (T, U) where T: View, U: View {
    fn render(&mut self, context: &Context) -> Id<Primitive> {
        context.identify(Primitive::Tuple2 {
            child1: Box::new(self.0.render(&context.child(0))),
            child2: Box::new(self.1.render(&context.child(1))),
        })
    }
}

impl<T, U, V> View for (T, U, V) where T: View, U: View, V: View {
    fn render(&mut self, context: &Context) -> Id<Primitive> {
        context.identify(Primitive::Tuple3 {
            child1: Box::new(self.0.render(&context.child(0))),
            child2: Box::new(self.1.render(&context.child(1))),
            child3: Box::new(self.2.render(&context.child(2))),
        })
    }
}

impl<T, U, V, W> View for (T, U, V, W) where T: View, U: View, V: View, W: View {
    fn render(&mut self, context: &Context) -> Id<Primitive> {
        context.identify(Primitive::Tuple4 {
            child1: Box::new(self.0.render(&context.child(0))),
            child2: Box::new(self.1.render(&context.child(1))),
            child3: Box::new(self.2.render(&context.child(2))),
            child4: Box::new(self.3.render(&context.child(3))),
        })
    }
}

impl<T, U, V, W, X> View for (T, U, V, W, X) where T: View, U: View, V: View, W: View, X: View {
    fn render(&mut self, context: &Context) -> Id<Primitive> {
        context.identify(Primitive::Tuple5 {
            child1: Box::new(self.0.render(&context.child(0))),
            child2: Box::new(self.1.render(&context.child(1))),
            child3: Box::new(self.2.render(&context.child(2))),
            child4: Box::new(self.3.render(&context.child(3))),
            child5: Box::new(self.4.render(&context.child(4))),
        })
    }
}