diff --git a/src/widget/position/set_size.rs b/src/widget/position/set_size.rs index ffb4e52..8ec989e 100644 --- a/src/widget/position/set_size.rs +++ b/src/widget/position/set_size.rs @@ -8,7 +8,20 @@ pub struct SetSize { impl Widget for SetSize { fn draw(&mut self, painter: &mut Painter) -> Size { - let child = painter.widget(&self.inner).size(); + // A declared length is what the child gets, whatever box this widget + // was offered before its parent knew that. Measuring it anywhere else + // asks about a box it will not have, and the answer on the other axis + // is taken under that: a wrapping text measured in the whole width + // reports one line, and nothing revisits it once the real width + // arrives. + let mut region = UiRegion::FULL; + for (axis, len) in [(Axis::X, self.x), (Axis::Y, self.y)] { + if let Some(len) = len { + let span = region.axis_mut(axis); + span.end = span.start + len.apply_rest(); + } + } + let child = painter.widget_within(&self.inner, region).size(); Size { x: self.x.unwrap_or(child.x), y: self.y.unwrap_or(child.y), diff --git a/tests/trace_unsettled.rs b/tests/trace_unsettled.rs new file mode 100644 index 0000000..ea61ef6 --- /dev/null +++ b/tests/trace_unsettled.rs @@ -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 { + 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(); +}