Make alignment a widget property
This commit is contained in:
1 parent
8220a78d4a
commit
d3b0ebf90c
21 files changed
+823
-300
No files matched your search
+92
-21
@@ -76,9 +76,9 @@ enum Node {
|
||||
fn axis_align(v: u8) -> Option<AxisAlign> {
|
||||
match v % 4 {
|
||||
0 => None,
|
||||
1 => Some(AxisAlign::Neg),
|
||||
2 => Some(AxisAlign::Center),
|
||||
_ => Some(AxisAlign::Pos),
|
||||
1 => Some(AxisAlign::NEG),
|
||||
2 => Some(AxisAlign::CENTER),
|
||||
_ => Some(AxisAlign::POS),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ impl Node {
|
||||
h: &mut Harness,
|
||||
out: &mut Vec<WidgetId>,
|
||||
spans: &mut Vec<WeakWidget<Span>>,
|
||||
sized: &mut Vec<WidgetId>,
|
||||
) -> StrongWidget {
|
||||
let id: StrongWidget = match self {
|
||||
Node::Text(words, wrap) => {
|
||||
@@ -106,7 +107,10 @@ impl Node {
|
||||
Node::OneLine => wtext(ONE_LINE).size(16).wrap(false).add_strong(&mut h.rsc),
|
||||
Node::Rect => rect(Color::RED).add_strong(&mut h.rsc),
|
||||
Node::Span(down, gap, kids, order) => {
|
||||
let mut built: Vec<_> = kids.iter().map(|k| Some(k.build(h, out, spans))).collect();
|
||||
let mut built: Vec<_> = kids
|
||||
.iter()
|
||||
.map(|k| Some(k.build(h, out, spans, sized)))
|
||||
.collect();
|
||||
// `order` is a permutation, so each is taken exactly once.
|
||||
let children = order
|
||||
.iter()
|
||||
@@ -126,7 +130,7 @@ impl Node {
|
||||
handle.add_strong(&mut h.rsc)
|
||||
}
|
||||
Node::Stack(kids) => {
|
||||
let children = kids.iter().map(|k| k.build(h, out, spans)).collect();
|
||||
let children = kids.iter().map(|k| k.build(h, out, spans, sized)).collect();
|
||||
Stack {
|
||||
children,
|
||||
size: StackSize::Child(0),
|
||||
@@ -134,7 +138,7 @@ impl Node {
|
||||
.add_strong(&mut h.rsc)
|
||||
}
|
||||
Node::Pad(p, kid) => {
|
||||
let inner = kid.build(h, out, spans);
|
||||
let inner = kid.build(h, out, spans, sized);
|
||||
Pad {
|
||||
padding: Padding {
|
||||
left: *p,
|
||||
@@ -147,30 +151,29 @@ impl Node {
|
||||
.add_strong(&mut h.rsc)
|
||||
}
|
||||
Node::Aligned(x, y, kid) => {
|
||||
let inner = kid.build(h, out, spans);
|
||||
Aligned {
|
||||
inner,
|
||||
align: Align {
|
||||
x: axis_align(*x),
|
||||
y: axis_align(*y),
|
||||
},
|
||||
let inner = kid.build(h, out, spans, sized);
|
||||
for (axis, align) in [(Axis::X, axis_align(*x)), (Axis::Y, axis_align(*y))] {
|
||||
if let Some(align) = align {
|
||||
h.rsc.widgets_mut().set_alignment(&inner, axis, align);
|
||||
}
|
||||
}
|
||||
.add_strong(&mut h.rsc)
|
||||
inner
|
||||
}
|
||||
Node::Sized(x, y, kid) => {
|
||||
let inner = kid.build(h, out, spans);
|
||||
let inner = kid.build(h, out, spans, sized);
|
||||
h.rsc.widgets_mut().set_size_rules(&inner, *x, *y);
|
||||
sized.push(inner.id());
|
||||
inner
|
||||
}
|
||||
Node::Scroll(down, kid) => {
|
||||
let inner = kid.build(h, out, spans);
|
||||
let inner = kid.build(h, out, spans, sized);
|
||||
let axis = if *down { Axis::Y } else { Axis::X };
|
||||
Scroll::new(inner, axis).add_strong(&mut h.rsc)
|
||||
}
|
||||
Node::Branch(probe, a, b, at) => {
|
||||
let probe = probe.build(h, out, spans);
|
||||
let wide = a.build(h, out, spans);
|
||||
let narrow = b.build(h, out, spans);
|
||||
let probe = probe.build(h, out, spans, sized);
|
||||
let wide = a.build(h, out, spans, sized);
|
||||
let narrow = b.build(h, out, spans, sized);
|
||||
Branch {
|
||||
probe,
|
||||
wide,
|
||||
@@ -184,6 +187,27 @@ impl Node {
|
||||
id
|
||||
}
|
||||
|
||||
/// The lengths every `Sized` node would carry after `resized`, in the
|
||||
/// order `build` pushes them.
|
||||
fn sized_lens(&self, out: &mut Vec<(Option<Len>, Option<Len>)>) {
|
||||
match self {
|
||||
Node::Text(..) | Node::OneLine | Node::Rect => {}
|
||||
Node::Span(_, _, kids, _) | Node::Stack(kids) => {
|
||||
kids.iter().for_each(|k| k.sized_lens(out));
|
||||
}
|
||||
Node::Pad(_, k) | Node::Aligned(_, _, k) | Node::Scroll(_, k) => k.sized_lens(out),
|
||||
Node::Sized(x, y, k) => {
|
||||
k.sized_lens(out);
|
||||
out.push((resized_len(*x), resized_len(*y)));
|
||||
}
|
||||
Node::Branch(p, a, b, _) => {
|
||||
p.sized_lens(out);
|
||||
a.sized_lens(out);
|
||||
b.sized_lens(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
1 + match self {
|
||||
Node::Text(..) | Node::OneLine | Node::Rect => 0,
|
||||
@@ -377,6 +401,41 @@ enum Case {
|
||||
Repaint,
|
||||
ResizeRepaint,
|
||||
Reorder,
|
||||
SizeChange,
|
||||
}
|
||||
|
||||
/// A different declared length, kept the same kind so the change is to the
|
||||
/// value alone.
|
||||
fn resized_len(len: Option<Len>) -> Option<Len> {
|
||||
len.map(|len| Len {
|
||||
px: len.px * 0.5 + 13.0,
|
||||
rel: len.rel * 0.5,
|
||||
leftover: len.leftover,
|
||||
})
|
||||
}
|
||||
|
||||
/// Every declared size changed, as a tree rather than as a change.
|
||||
fn resized(node: &Node) -> Node {
|
||||
match node {
|
||||
Node::Span(down, gap, kids, order) => Node::Span(
|
||||
*down,
|
||||
*gap,
|
||||
kids.iter().map(resized).collect(),
|
||||
order.clone(),
|
||||
),
|
||||
Node::Stack(kids) => Node::Stack(kids.iter().map(resized).collect()),
|
||||
Node::Pad(p, k) => Node::Pad(*p, Box::new(resized(k))),
|
||||
Node::Aligned(x, y, k) => Node::Aligned(*x, *y, Box::new(resized(k))),
|
||||
Node::Sized(x, y, k) => Node::Sized(resized_len(*x), resized_len(*y), Box::new(resized(k))),
|
||||
Node::Scroll(d, k) => Node::Scroll(*d, Box::new(resized(k))),
|
||||
Node::Branch(p, a, b, at) => Node::Branch(
|
||||
Box::new(resized(p)),
|
||||
Box::new(resized(a)),
|
||||
Box::new(resized(b)),
|
||||
*at,
|
||||
),
|
||||
leaf => leaf.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Every span's children rotated by one, as a tree rather than as a change:
|
||||
@@ -413,7 +472,8 @@ fn diverges(node: &Node, case: Case) -> Option<String> {
|
||||
let mut warm = Harness::new(start);
|
||||
let mut warm_ids = Vec::new();
|
||||
let mut warm_spans = Vec::new();
|
||||
let root = node.build(&mut warm, &mut warm_ids, &mut warm_spans);
|
||||
let mut warm_sized = Vec::new();
|
||||
let root = node.build(&mut warm, &mut warm_ids, &mut warm_spans, &mut warm_sized);
|
||||
warm.state.root = Some(root);
|
||||
// The frame that makes it warm: without it there is nothing retained and
|
||||
// the comparison is two cold starts agreeing with each other.
|
||||
@@ -434,16 +494,26 @@ fn diverges(node: &Node, case: Case) -> Option<String> {
|
||||
}
|
||||
warm.frame();
|
||||
}
|
||||
if case == Case::SizeChange {
|
||||
let mut lens = Vec::new();
|
||||
node.sized_lens(&mut lens);
|
||||
for (id, (x, y)) in warm_sized.iter().zip(lens) {
|
||||
warm.rsc.widgets_mut().set_size_rules(*id, x, y);
|
||||
}
|
||||
warm.frame();
|
||||
}
|
||||
|
||||
// What the warm tree was moved into, grown that way from the start.
|
||||
let want = match case {
|
||||
Case::Reorder => reordered(node),
|
||||
Case::SizeChange => resized(node),
|
||||
_ => node.clone(),
|
||||
};
|
||||
let mut cold = Harness::new(INNER);
|
||||
let mut cold_ids = Vec::new();
|
||||
let mut cold_spans = Vec::new();
|
||||
let root = want.build(&mut cold, &mut cold_ids, &mut cold_spans);
|
||||
let mut cold_sized = Vec::new();
|
||||
let root = want.build(&mut cold, &mut cold_ids, &mut cold_spans, &mut cold_sized);
|
||||
cold.state.root = Some(root);
|
||||
cold.frame();
|
||||
|
||||
@@ -497,6 +567,7 @@ fn no_grown_tree_lays_out_differently_warm_than_cold() {
|
||||
"repaint" => Case::Repaint,
|
||||
"resize-repaint" => Case::ResizeRepaint,
|
||||
"reorder" => Case::Reorder,
|
||||
"size-change" => Case::SizeChange,
|
||||
_ => Case::Resize,
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user