Retain frame and extent dependencies independently
Keep the original measurement placement separate from the assigned slot.
Validate frame and extent lengths before reusing an answer or drawing, and
represent hint-only records as having no measured answer.
Retain primitive and mask coordinates with their frame/extent reference.
Forwarded children follow a reused wrapper's placement without rerunning
valid draw bodies. Keep the single Widget::draw API.
Restore the eight failing suite cases from the region/placement prototype,
with regressions for mixed coordinate references, a changed inherited
extent, the sizing-stack fraction, and an undrawn share becoming visible.
This remains experimental: nested container updates do substantially more
work than e44dea3 despite restoring the leaf and wrapper reuse guarantees.
Do not merge it as a performance improvement.
This commit is contained in:
1 parent
5fcace1bfa
commit
efb416bbc3
14 files changed
+548
-166
No files matched your search
+81
-10
@@ -156,16 +156,9 @@ fn a_span_child_that_declares_its_length_is_drawn_once() {
|
||||
h.set_root((hinted, asked).span(Dir::RIGHT));
|
||||
|
||||
assert_eq!(told_draws.get(), 1);
|
||||
// Reading its box makes its drawing hold for the measuring box alone,
|
||||
// and it reports less than that box: so it is drawn again in the box its
|
||||
// answer places it in, and once more in the final box the span chooses.
|
||||
// A widget that says what it holds for, as text does, skips the middle
|
||||
// one.
|
||||
assert_eq!(
|
||||
asked_draws.get(),
|
||||
3,
|
||||
"drawn to be measured, in its placed box, then in its final box"
|
||||
);
|
||||
// Only the available length changes: positioning the final slot does
|
||||
// not invalidate a numeric size read.
|
||||
assert_eq!(asked_draws.get(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -737,3 +730,81 @@ fn a_subtree_that_changed_parents_settles_at_the_depth_it_moved_to() {
|
||||
"the span it moved to is the one the change has to reach"
|
||||
);
|
||||
}
|
||||
|
||||
fn primitive_bounds(h: &Harness, id: WidgetId) -> Vec<PixelRegion> {
|
||||
h.render.active[&id]
|
||||
.primitives
|
||||
.iter()
|
||||
.map(|primitive| {
|
||||
let handle = &primitive.handle;
|
||||
let instance = &h.render.layers[handle.layer].primitives()[handle.kind as usize]
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.instances()[handle.inst_idx];
|
||||
h.render
|
||||
.moves
|
||||
.resolve(instance.move_idx, instance.region)
|
||||
.to_px(h.render.output_size())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_geometry_and_extent_geometry_keep_their_references() {
|
||||
struct Both(Rc<Cell<usize>>);
|
||||
impl Widget for Both {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
self.0.set(self.0.get() + 1);
|
||||
painter.primitive_within(RectPrimitive::color(Color::RED), UiRegion::FULL);
|
||||
painter.primitive(RectPrimitive::color(Color::BLUE));
|
||||
Size::LEFTOVER
|
||||
}
|
||||
}
|
||||
for node in [false, true] {
|
||||
let mut h = Harness::new((400, 200));
|
||||
let first = rect(Color::GREEN).width(100).add(&mut h.rsc);
|
||||
let draws = Rc::new(Cell::new(0));
|
||||
let both = Both(draws.clone()).add(&mut h.rsc);
|
||||
h.rsc.widgets_mut().set_region_node(both, node);
|
||||
h.set_root((first, both).span(Dir::RIGHT));
|
||||
let count = draws.get();
|
||||
h.set_len(first, Axis::X, 200);
|
||||
h.frame();
|
||||
assert_eq!(draws.get(), count);
|
||||
let bounds = primitive_bounds(&h, both.id());
|
||||
assert_eq!(bounds[0].top_left.x, Px::ZERO);
|
||||
assert_eq!(bounds[0].bot_right.x, Px::from_int(400));
|
||||
assert_eq!(bounds[1].top_left.x, Px::from_int(200));
|
||||
assert_eq!(bounds[1].bot_right.x, Px::from_int(400));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changing_an_inherited_extent_keeps_the_original_measurement_offer() {
|
||||
fn build(h: &mut Harness, width: i32, text: &str) -> (WeakWidget<Text>, WeakWidget<Rect>) {
|
||||
let first = rect(Color::RED).width(width).add(&mut h.rsc);
|
||||
let words = wtext(text).size(20).wrap(true).add(&mut h.rsc);
|
||||
let through = Stretchy {
|
||||
inner: words.add_strong(&mut h.rsc),
|
||||
draws: Rc::new(Cell::new(0)),
|
||||
}
|
||||
.add(&mut h.rsc);
|
||||
h.set_root((first, through).span(Dir::RIGHT));
|
||||
(words, first)
|
||||
}
|
||||
let short = "one two";
|
||||
let long = "one two three four five six seven eight nine ten eleven twelve";
|
||||
let mut warm = Harness::new((400, 200));
|
||||
let (words, first) = build(&mut warm, 50, short);
|
||||
warm.set_len(first, Axis::X, 200);
|
||||
warm.frame();
|
||||
*warm.rsc[words].content = long.to_string();
|
||||
warm.frame();
|
||||
let mut cold = Harness::new((400, 200));
|
||||
let (other, _) = build(&mut cold, 200, long);
|
||||
assert_eq!(warm.region(&words), cold.region(&other));
|
||||
assert_eq!(
|
||||
primitive_bounds(&warm, words.id()),
|
||||
primitive_bounds(&cold, other.id())
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user