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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use tui::layout::{Constraint, Direction, Layout};
use super::{Flex, FlexArray};
use crate::{
component,
components::children::Children,
element::{Any as AnyElement, Element},
event::{self, KeyEvent, KeyHandler, MouseEvent, MouseHandler},
terminal::{Frame, Rect},
};
#[component(Stack<const N: usize>)]
pub fn render(flex: FlexArray<N>, children: Children<N>, on_key: KeyHandler, on_mouse: MouseHandler) {
AnyElement::new(Frozen {
flex: *flex,
children: children.render(),
on_key: on_key.clone(),
on_mouse: on_mouse.clone(),
})
}
struct Frozen<const N: usize> {
flex: FlexArray<N>,
children: [AnyElement; N],
on_key: KeyHandler,
on_mouse: MouseHandler,
}
impl<const N: usize> Frozen<N> {
fn layout(&self, rect: Rect) -> Vec<Rect> {
let total_grow: u16 = self
.flex
.iter()
.map(|flex| match flex {
Flex::Grow(grow) => *grow,
Flex::Block(_) => 0,
})
.sum();
let total_px: u16 = self
.flex
.iter()
.map(|flex| match flex {
Flex::Block(px) => *px,
Flex::Grow(_) => 0,
})
.sum();
let grow_px = rect.width - total_px;
Layout::default()
.direction(Direction::Horizontal)
.constraints(self.flex.map(|flex| match flex {
Flex::Block(px) => Constraint::Length(px),
Flex::Grow(grow) => Constraint::Length(grow * grow_px / total_grow),
}))
.split(rect)
}
}
impl<const N: usize> Element for Frozen<N> {
fn on_key(&self, event: KeyEvent) {
self.on_key.handle(event);
}
fn on_mouse(&self, rect: Rect, event: MouseEvent) {
self.on_mouse.handle_or(event, |event| {
for (i, rect) in self.layout(rect).into_iter().enumerate() {
if event::is_within(&event, rect) {
self.children[i].on_mouse(rect, event);
break;
}
}
});
}
fn draw(&self, rect: Rect, frame: &mut Frame) {
let layout = self.layout(rect);
for (i, child) in self.children.iter().enumerate() {
child.draw(*layout.get(i).expect("missing rect"), frame);
}
}
}