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
use std::rc::Rc;
use pax::*;
use pax::api::{Size2D, Size, ArgsRender, Property};
use crate::primitives::{Frame, Group};
use crate::types::{StackerDirection, StackerCellProperties};
#[pax(
for (elem, i) in self.computed_layout_spec {
<Frame transform={translate(elem.x_px, elem.y_px)} size={(elem.width_px, elem.height_px)}>
slot(i)
</Frame>
}
)]
pub struct Stacker {
pub computed_layout_spec: Property<Vec<Rc<StackerCellProperties>>>,
pub direction: Property<StackerDirection>,
pub cells: Property<usize>,
pub gutter_width: Property<Size>,
pub overrides_cell_size: Property<Vec<(usize, Size)>>,
pub overrides_gutter_size: Property<Vec<(usize, Size)>>,
}
impl Stacker {
#[pax_on(WillRender)]
pub fn handle_will_render(&mut self, args: ArgsRender) {
let bounds = args.bounds;
let active_bound = match *self.direction.get() {
StackerDirection::Horizontal => bounds.0,
StackerDirection::Vertical => bounds.1
};
let gutter_calc = match *self.gutter_width.get() {
Size::Pixels(px) => px,
Size::Percent(pct) => active_bound * (pct / 100.0),
};
let cells = *self.cells.get() as f64;
let usable_interior_space = active_bound - (cells - 1.0) * gutter_calc;
let per_cell_space = usable_interior_space / cells;
let old = self.computed_layout_spec.get();
let new : Vec<Rc<StackerCellProperties>> = (0..(cells as usize)).into_iter().map(|i| {
match self.direction.get() {
StackerDirection::Horizontal =>
Rc::new(StackerCellProperties {
height_px: bounds.1,
width_px: per_cell_space,
x_px: ((i) as f64) * (gutter_calc) + (i as f64) * per_cell_space,
y_px: 0.0,
}),
StackerDirection::Vertical =>
Rc::new(StackerCellProperties {
height_px: per_cell_space,
width_px: bounds.0,
x_px: 0.0,
y_px: ((i) as f64) * (gutter_calc) + (i as f64) * per_cell_space,
}),
}
}).collect();
let is_dirty = old.len() != new.len() || old.iter().enumerate().any(|(i,p_old)|{
let p_new = new.get(i).unwrap();
p_old.height_px != p_new.height_px ||
p_old.width_px != p_new.width_px ||
p_old.x_px != p_new.x_px ||
p_old.y_px != p_new.y_px
});
if is_dirty {
self.computed_layout_spec.set(new);
}
}
}