Six widgets from 905, and it fails in 0.06s: everything inside a declared 189x176 box is the same size whatever the output is, so a resize may not reach any of it, and the text still comes out 3.92px narrower warm than cold. `tests/trace_unsettled.rs` says why, and it is not what it looked like. A span measures a content-sized child in the space remaining, is told 167.41, and then offers that back as the child's box -- so the text is re-broken at exactly its own longest line, which is a knife edge: warm lands on four lines and 163.49, cold stays on three and 167.41. Measuring an answer against itself is unstable precisely at the fixed point. `Painter::settle` -- move the child's slot, keep the drawing, never measure again -- is the shape of the fix and does not work yet. In a span it breaks five cases, because a container child may have laid its own children out as fractions of the box it drew in, so moving it into a shorter one shrinks them; reporting a length in pixels does not mean the drawing is positioned in pixels. In `Aligned` alone it breaks two. Recorded rather than kept: the condition wants to be something a widget declares, near `OnResize`, rather than something its caller infers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
156 lines
4.5 KiB
Rust
156 lines
4.5 KiB
Rust
//! 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();
|
|
}
|
|
|
|
fn plant_fixed(h: &mut Harness) -> Vec<WidgetId> {
|
|
let words = "Wrapping shapes one source into as many lines as the box leaves";
|
|
let text = wtext(words).size(16).wrap(true).add(&mut h.rsc);
|
|
let aligned = Aligned {
|
|
inner: text.add_strong(&mut h.rsc),
|
|
align: Align {
|
|
x: Some(AxisAlign::Neg),
|
|
y: None,
|
|
},
|
|
}
|
|
.add(&mut h.rsc);
|
|
let inner = (aligned,).span(Dir::RIGHT).add(&mut h.rsc);
|
|
let sized = SetSize {
|
|
inner: inner.add_strong(&mut h.rsc),
|
|
x: Some(Len::px(189.0)),
|
|
y: Some(Len::px(176.0)),
|
|
}
|
|
.add(&mut h.rsc);
|
|
let filler = rect(Color::RED).add(&mut h.rsc);
|
|
let root = (filler, sized).span(Dir::RIGHT).add(&mut h.rsc);
|
|
h.state.root = Some(root.add_strong(&mut h.rsc));
|
|
vec![
|
|
text.id(),
|
|
aligned.id(),
|
|
inner.id(),
|
|
sized.id(),
|
|
filler.id(),
|
|
root.id(),
|
|
]
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "a diagnostic, not a check"]
|
|
fn what_box_the_fixed_text_is_drawn_in() {
|
|
diag::clear_traced_widgets();
|
|
let _ = diag::take();
|
|
let mut h = Harness::new((1920, 1200));
|
|
let ids = plant_fixed(&mut h);
|
|
let text = ids[0];
|
|
diag::trace_widget(text);
|
|
let _ = diag::take();
|
|
|
|
h.frame();
|
|
dump("first frame at 1920", &diag::take(), text);
|
|
h.resize((640, 900));
|
|
h.frame();
|
|
dump("after resize to 640", &diag::take(), text);
|
|
|
|
let mut cold = Harness::new((640, 900));
|
|
let cids = plant_fixed(&mut cold);
|
|
diag::clear_traced_widgets();
|
|
diag::trace_widget(cids[0]);
|
|
let _ = diag::take();
|
|
cold.frame();
|
|
dump("cold at 640", &diag::take(), cids[0]);
|
|
diag::clear_traced_widgets();
|
|
}
|