Settle growing layout branches in one frame
This commit is contained in:
1 parent
f95835593f
commit
46e6edfd0b
3 files changed
+90
-4
No files matched your search
@@ -1172,3 +1172,67 @@ fn a_span_of_padded_children_inside_a_span_draws_each_where_its_box_is() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Growing an already-drawn row first measures its new child against the
|
||||
/// row's old height. That provisional box can end before it starts when the
|
||||
/// old trailing edge is above the new child's cursor. The size must bubble to
|
||||
/// `LazySpan` and the corrected allocation must travel back down before this
|
||||
/// update is presented; a later stream event is not a layout pass.
|
||||
#[test]
|
||||
fn a_new_child_in_a_growing_lazy_row_uses_its_final_box_immediately() {
|
||||
const FIRST: f32 = 30.0;
|
||||
const SECOND: f32 = 70.0;
|
||||
const GAP: f32 = 8.0;
|
||||
|
||||
let mut rsc = TestRsc {
|
||||
ui: UiData::default(),
|
||||
};
|
||||
let first = rsc.ui.widgets.add_strong(Rect::new(UiColor::WHITE));
|
||||
let first_id = first.id();
|
||||
let first = rsc.ui.widgets.add_strong(Sized {
|
||||
inner: first.any(),
|
||||
x: None,
|
||||
y: Some(Len::abs(FIRST)),
|
||||
});
|
||||
let mut contents = Span::empty(Dir::DOWN).gap(Len::abs(GAP));
|
||||
contents.push(first.any());
|
||||
let contents = rsc.ui.widgets.add_strong(contents);
|
||||
let contents_w = contents.weak();
|
||||
let row = rsc.ui.widgets.add_strong(Sized {
|
||||
inner: contents.any(),
|
||||
x: Some(Len::rest(1.0)),
|
||||
y: None,
|
||||
});
|
||||
let mut list = LazySpan::new(Dir::DOWN, Pin::End);
|
||||
list.push_back(LazyItem::new(0, row.any()));
|
||||
let root = rsc.ui.widgets.add_strong(list).any();
|
||||
|
||||
let mut render = UiRenderState::new();
|
||||
render.resize((200.0, 200.0));
|
||||
render.update(&root, &mut rsc);
|
||||
|
||||
let second = rsc.ui.widgets.add_strong(Rect::new(UiColor::WHITE));
|
||||
let second_id = second.id();
|
||||
let second = rsc.ui.widgets.add_strong(Sized {
|
||||
inner: second.any(),
|
||||
x: None,
|
||||
y: Some(Len::abs(SECOND)),
|
||||
});
|
||||
rsc.ui
|
||||
.widgets
|
||||
.get_mut(&contents_w)
|
||||
.unwrap()
|
||||
.push(second.any());
|
||||
render.update(&root, &mut rsc);
|
||||
|
||||
let first = render.primitive_corners(render.first_primitive(first_id).unwrap(), &rsc);
|
||||
let second = render.primitive_corners(render.first_primitive(second_id).unwrap(), &rsc);
|
||||
assert!(
|
||||
(second.top_left.y - (first.bot_right.y + GAP)).abs() < 0.01,
|
||||
"the new child should start after the old child and its gap: first={first:?} second={second:?}"
|
||||
);
|
||||
assert!(
|
||||
(second.bot_right.y - second.top_left.y - SECOND).abs() < 0.01,
|
||||
"the new child retained its provisional box: {second:?}"
|
||||
);
|
||||
}
|
||||
@@ -31,4 +31,12 @@ impl Widget for Sized {
|
||||
Axis::Y => self.y,
|
||||
}
|
||||
}
|
||||
|
||||
fn requires_exact_region(&self) -> bool {
|
||||
// `Sized` may be measured in a provisional box and then placed in
|
||||
// the content-sized box it reported. Its own region can be corrected
|
||||
// by a move, but its child consumed the original box and must see the
|
||||
// final one too.
|
||||
true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user