Measure a child in the length its parent declared, not the box it was offered
`SetSize` drew its child in whatever box it had been given and then reported its declared length, so the child answered about a box it was never going to have -- and the answer on the *other* axis was taken under that. A wrapping text under `SetSize(x: 76px)` was measured in the whole 640 available, reported one line, and the parent sized itself to one line. The text was then drawn again at 76 and reported two, but by then its box was settled and nothing revisited it. A repaint put it right, which is why the first frame and the second disagreed. So the layout was not a function of the state, and "cold" was not a fixed point -- which means the warm-against-cold oracle has been measuring against a tree that had not settled, and some of what it reported as a retained-layout defect was the cold side being wrong. Nothing about retained state is involved in this: it reproduces in six widgets on a first frame. The declared length is what the child gets, so that is where it is measured. `apply_rest` carries `rel` and `rest` through unchanged, and a `px` length composes as an offset, so the child's box does not move again when this widget's own box shrinks to what it declared. `tests/unsettled.rs` passes, and the generated sweep now passes at depth 5 where it failed. Depth 6 and 7 still fail; there is more than one of these. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f0c7df06ac
commit
c596bf12c6
2 files changed
+111
-1
No files matched your search
@@ -0,0 +1,97 @@
|
||||
//! Traces the six-widget tree in `unsettled.rs`, to see what box its text is
|
||||
//! actually drawn in on a first frame against a settled one.
|
||||
|
||||
#![cfg(feature = "layout-diagnostics")]
|
||||
|
||||
use iris::core::layout_diagnostics::{self as diag, TraceEvent};
|
||||
use iris::harness::Harness;
|
||||
use iris::prelude::*;
|
||||
|
||||
fn plant(h: &mut Harness) -> Vec<WidgetId> {
|
||||
let plain = wtext("Wrapping").size(16).wrap(false).add(&mut h.rsc);
|
||||
let wrapped = wtext("Wrapping shapes").size(16).wrap(true).add(&mut h.rsc);
|
||||
let sized = SetSize {
|
||||
inner: wrapped.add_strong(&mut h.rsc),
|
||||
x: Some(Len::px(76.0)),
|
||||
y: None,
|
||||
}
|
||||
.add(&mut h.rsc);
|
||||
let aligned = Aligned {
|
||||
inner: sized.add_strong(&mut h.rsc),
|
||||
align: Align {
|
||||
x: Some(AxisAlign::Pos),
|
||||
y: Some(AxisAlign::Pos),
|
||||
},
|
||||
}
|
||||
.add(&mut h.rsc);
|
||||
let stack = Stack {
|
||||
children: vec![plain.add_strong(&mut h.rsc), aligned.add_strong(&mut h.rsc)],
|
||||
size: StackSize::Child(0),
|
||||
}
|
||||
.add(&mut h.rsc);
|
||||
let root = (stack,).span(Dir::RIGHT).add(&mut h.rsc);
|
||||
h.state.root = Some(root.add_strong(&mut h.rsc));
|
||||
vec![
|
||||
plain.id(),
|
||||
wrapped.id(),
|
||||
sized.id(),
|
||||
aligned.id(),
|
||||
stack.id(),
|
||||
root.id(),
|
||||
]
|
||||
}
|
||||
|
||||
fn dump(label: &str, report: &diag::Report, text: WidgetId) {
|
||||
println!("--- {label} ---");
|
||||
for event in report.traces() {
|
||||
match event {
|
||||
TraceEvent::DrawRequest {
|
||||
id,
|
||||
region,
|
||||
pixel_size,
|
||||
..
|
||||
} if *id == text => {
|
||||
println!(
|
||||
" draw in {:.2}x{:.2} region {region:?}",
|
||||
pixel_size.x, pixel_size.y
|
||||
)
|
||||
}
|
||||
TraceEvent::SizeReported { id, size } if *id == text => {
|
||||
println!(" reported {size}")
|
||||
}
|
||||
TraceEvent::SizeRead { id, reader, size } if *id == text => {
|
||||
println!(" size read by {reader:?}: {size}")
|
||||
}
|
||||
TraceEvent::Placed { id, parent, region } if *id == text => {
|
||||
println!(" placed by {parent:?} at {region:?}")
|
||||
}
|
||||
TraceEvent::Reuse { id, outcome } if *id == text => println!(" reuse: {outcome:?}"),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "a diagnostic, not a check"]
|
||||
fn what_box_the_text_is_drawn_in() {
|
||||
diag::clear_traced_widgets();
|
||||
let _ = diag::take();
|
||||
let mut h = Harness::new((640, 900));
|
||||
let ids = plant(&mut h);
|
||||
let text = ids[1];
|
||||
diag::trace_widget(text);
|
||||
let _ = diag::take();
|
||||
|
||||
h.frame();
|
||||
dump("first frame", &diag::take(), text);
|
||||
|
||||
for _ in 0..2 {
|
||||
for &id in &ids {
|
||||
h.rsc.widgets_mut().get_dyn_mut(id);
|
||||
}
|
||||
let _ = diag::take();
|
||||
h.frame();
|
||||
dump("repaint", &diag::take(), text);
|
||||
}
|
||||
diag::clear_traced_widgets();
|
||||
}
|
||||
Reference in new issue
Block a user