diff --git a/tests/cases/plan.rs b/tests/cases/plan.rs index a9baab5..031d244 100644 --- a/tests/cases/plan.rs +++ b/tests/cases/plan.rs @@ -70,11 +70,13 @@ fn editing_a_plan_is_growing_one_with_those_edits() { } } -/// Every simplification is strictly smaller, so taking them in turn reaches a -/// fixed point instead of circling. A shrinker that can return to a tree it -/// has already tried does not stop. +/// No simplification is larger, which is the half of "the shrinker stops" a +/// widget count can see. Most are not smaller either -- a dropped alignment +/// and a simpler leaf both keep the count -- so what rules out circling is +/// that those are one-way too: a `Some` becomes a `None`, and a kind steps +/// down a ladder with no way back up. #[test] -fn every_simplification_of_a_plan_is_smaller_than_it() { +fn no_simplification_of_a_plan_is_larger_than_it() { for seed in 1..=60 { let tree = plan(seed, 4, &Edits::default()); let mut queue = vec![tree]; diff --git a/tests/cases/retained.rs b/tests/cases/retained.rs index 358097d..5393ea9 100644 --- a/tests/cases/retained.rs +++ b/tests/cases/retained.rs @@ -45,7 +45,6 @@ fn counted(h: &mut Harness, size: Size, reads_box: bool) -> (WeakWidget struct Layered { children: [StrongWidget; 2], - _revision: usize, } impl Widget for Layered { @@ -65,14 +64,10 @@ fn a_redrawn_layered_widget_keeps_the_layer_it_was_entered_on() { rect(Color::RED).add_strong(&mut h.rsc), rect(Color::BLUE).add_strong(&mut h.rsc), ]; - let root = Layered { - children, - _revision: 0, - } - .add(&mut h.rsc); + let root = Layered { children }.add(&mut h.rsc); h.set_root(root); - h.rsc[root]._revision += 1; + h.rsc.widgets_mut().get_dyn_mut(root.id()); h.frame(); let label = h.rsc.widgets().label(root.id()); @@ -774,6 +769,17 @@ fn a_subtree_that_changed_parents_settles_at_the_depth_it_moved_to() { ); } +/// Where a mask slot clips, in window pixels: the region it holds, carried +/// through whatever move entry it hangs from. Taken by slot rather than by +/// widget, so a test can name the slot it expects a redraw to keep. +fn mask_bounds(h: &Harness, mask: MaskIdx) -> PixelRegion { + let mask = &h.rsc.ui().masks[mask.idx()]; + h.render + .moves + .resolve(mask.move_idx, mask.region) + .to_px(h.render.output_size()) +} + fn primitive_bounds(h: &Harness, id: WidgetId) -> Vec { h.render.active[&id] .primitives @@ -919,15 +925,10 @@ fn resizing_a_fixed_frame_recomposes_its_contents_without_drawing_them() { primitive_bounds(&warm, leaf.id()), primitive_bounds(&cold, other.id()) ); - let mask = |h: &Harness, id: WidgetId| { - let active = &h.render.active[&id]; - let mask = &h.rsc.ui().masks[active.mask.idx()]; - h.render - .moves - .resolve(mask.move_idx, mask.region) - .to_px(h.render.output_size()) - }; - assert_eq!(mask(&warm, leaf.id()), mask(&cold, other.id())); + assert_eq!( + mask_bounds(&warm, warm.render.active[&leaf.id()].mask), + mask_bounds(&cold, cold.render.active[&other.id()].mask) + ); } } @@ -1184,15 +1185,10 @@ fn padding_and_stack_boxes_follow_the_region_without_drawing_again() { assert_eq!(warm.region(&a), cold.region(&b)); assert_eq!(primitive_bounds(&warm, a), primitive_bounds(&cold, b)); } - let mask = |h: &Harness, id: WidgetId| { - let active = &h.render.active[&id]; - let mask = &h.rsc.ui().masks[active.mask.idx()]; - h.render - .moves - .resolve(mask.move_idx, mask.region) - .to_px(h.render.output_size()) - }; - assert_eq!(mask(&warm, leaf.id()), mask(&cold, other.id())); + assert_eq!( + mask_bounds(&warm, warm.render.active[&leaf.id()].mask), + mask_bounds(&cold, cold.render.active[&other.id()].mask) + ); } } } @@ -1381,13 +1377,7 @@ fn a_redrawn_mask_keeps_reused_primitives_clipped_when_it_moves() { assert_eq!(h.render.active[&masked.id()].mask, mask); h.set_len(first, Axis::Y, 10); h.frame(); - let clip = h.rsc.ui().masks[mask.idx()]; - let clip = h - .render - .moves - .resolve(clip.move_idx, clip.region) - .to_px(h.render.output_size()); - assert_eq!(clip, h.region(&masked).unwrap()); + assert_eq!(mask_bounds(&h, mask), h.region(&masked).unwrap()); assert_corners!(h, inner, (0, 10), (400, 200)); } } diff --git a/tests/cases/scroll.rs b/tests/cases/scroll.rs index e7094c9..149774a 100644 --- a/tests/cases/scroll.rs +++ b/tests/cases/scroll.rs @@ -142,8 +142,8 @@ fn a_clipping_widget_reporting_more_than_its_box_is_caught() { let mut h = Harness::new((100, 100)); let tall = rect(Color::RED).height(400).add_strong(&mut h.rsc); let clipper = Clipper(tall).add(&mut h.rsc); + // `set_root` lays the tree out, so this is where it is caught. h.set_root(clipper); - h.frame(); } /// Content that fits sits in the viewport, not in a box of the window's diff --git a/tests/cases/unsettled.rs b/tests/cases/unsettled.rs index 1d472f5..7c0f51b 100644 --- a/tests/cases/unsettled.rs +++ b/tests/cases/unsettled.rs @@ -14,6 +14,9 @@ use iris::harness::Harness; use iris::prelude::*; use iris::random::Branch; +/// Every widget in the same place warm as cold, reported all at once: which +/// of a dozen boxes moved is the whole of what a shrunk case has to say. +#[track_caller] fn assert_same_regions( warm: &Harness, warm_ids: &[WidgetId], @@ -188,36 +191,31 @@ fn reordering_nested_spans_keeps_the_answer_from_the_decided_box() { assert_same_regions(&warm, &ids, &cold, &cold_ids); } -/// Six widgets, shrunk from a 402-widget tree the fuzzer found. Nothing about +/// Four widgets, shrunk from a 402-widget tree the fuzzer found. Nothing about /// the tree changes -- every widget is marked for redraw and the frame is /// taken again -- so no box may move, and a warm frame has to land where a /// cold one does. 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 = wrapped.width(76).add(&mut h.rsc); - let aligned = sized; + let wrapped = wtext("Wrapping shapes") + .size(16) + .wrap(true) + .width(76) + .add(&mut h.rsc); h.rsc .widgets_mut() - .set_alignment(sized, Axis::X, AxisAlign::POS); + .set_alignment(wrapped, Axis::X, AxisAlign::POS); h.rsc .widgets_mut() - .set_alignment(sized, Axis::Y, AxisAlign::POS); + .set_alignment(wrapped, Axis::Y, AxisAlign::POS); let stack = Stack { - children: vec![plain.add_strong(&mut h.rsc), aligned.add_strong(&mut h.rsc)], + children: vec![plain.add_strong(&mut h.rsc), wrapped.add_strong(&mut h.rsc)], size: StackSize::Child(0), } .add(&mut h.rsc); let root = (stack,).span(Dir::RIGHT).add(&mut h.rsc); h.set_root(root); - vec![ - plain.id(), - wrapped.id(), - sized.id(), - aligned.id(), - stack.id(), - root.id(), - ] + vec![plain.id(), wrapped.id(), stack.id(), root.id()] } /// The first frame does not reach the layout a second one does, so "cold" is @@ -259,39 +257,23 @@ fn repainting_everything_moves_nothing() { let mut cold = Harness::new((640, 900)); let cold_ids = plant(&mut cold); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } -/// Six widgets, shrunk from 905. Everything inside the declared 189x176 box +/// Four widgets, shrunk from 905. Everything inside the declared 189x176 box /// is the same size whatever the output is, so a resize may not change any of /// it -- but the text comes out 3.92px narrower warm than cold. fn plant_fixed(h: &mut Harness) -> Vec { 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 = text; h.rsc .widgets_mut() .set_alignment(text, Axis::X, AxisAlign::NEG); - let inner = (aligned,).span(Dir::RIGHT).add(&mut h.rsc); - let sized = inner.sized((189, 176)).add(&mut h.rsc); + let inner = (text,).span(Dir::RIGHT).sized((189, 176)).add(&mut h.rsc); let filler = rect(Color::RED).add(&mut h.rsc); - let root = (filler, sized).span(Dir::RIGHT).add(&mut h.rsc); + let root = (filler, inner).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(), - ] + vec![text.id(), inner.id(), filler.id(), root.id()] } #[test] @@ -306,17 +288,10 @@ fn a_resize_does_not_reach_inside_a_box_of_declared_pixels() { let cold_ids = plant_fixed(&mut cold); cold.frame(); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } -/// Four widgets, shrunk from 486. A span's two children are swapped: warm by +/// Three widgets, shrunk from 486. A span's two children are swapped: warm by /// moving them, cold by growing them that way. Same widgets, same sizes, one /// ends up 29.9px from where the other does. fn plant_pair(h: &mut Harness, swapped: bool) -> (Vec, WeakWidget) { @@ -340,16 +315,11 @@ fn plant_pair(h: &mut Harness, swapped: bool) -> (Vec, WeakWidget (Vec, [WeakWidget gap: Px::ZERO, } .add(&mut h.rsc); - let block = rect(Color::RED).add(&mut h.rsc); - let fixed = block.width(87).add(&mut h.rsc); + let fixed = rect(Color::RED).width(87).add(&mut h.rsc); let mut outer_children: Vec = vec![fixed.add_strong(&mut h.rsc), inner.add_strong(&mut h.rsc)]; if swapped { @@ -416,7 +378,6 @@ fn plant_scrolled(h: &mut Harness, swapped: bool) -> (Vec, [WeakWidget text.id(), filler.id(), inner.id(), - block.id(), fixed.id(), outer.id(), through.id(), @@ -440,14 +401,7 @@ fn a_span_given_the_box_its_answer_decided_matches_a_cold_layout() { let (cold_ids, _) = plant_scrolled(&mut cold, true); cold.frame(); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } /// Reports a width derived from the box it is asked in. Reading through the @@ -471,11 +425,10 @@ impl Widget for Wider { fn plant_wider(h: &mut Harness, extra: f32) -> (WeakWidget, WidgetId) { let content = Wider { extra }.add(&mut h.rsc); let scroll = Scroll::new(content.add_strong(&mut h.rsc), Axis::X).add(&mut h.rsc); - let root = scroll; h.rsc .widgets_mut() .set_alignment(scroll, Axis::X, AxisAlign::NEG); - h.set_root(root); + h.set_root(scroll); (content, scroll.id()) } @@ -567,14 +520,7 @@ fn a_box_that_only_rounds_past_its_fixed_children_leaves_nothing_over() { let (cold_ids, _) = plant_boundary(&mut cold, true); cold.frame(); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } /// Five widgets, shrunk by `tests/shrink.rs` from the 277 the oracle's seed @@ -622,14 +568,7 @@ fn redrawing_one_widget_does_not_move_what_scrolls_around_it() { let mut cold = Harness::new((900, 1200)); let cold_ids = plant_nested_scrolls(&mut cold); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } /// Ten widgets, of the shape `tests/shrink.rs` reduces the oracle's seed 220 @@ -720,14 +659,7 @@ fn a_widget_under_a_region_node_is_asked_in_the_box_that_node_was_offered() { let (cold_ids, _) = plant_under_a_node(&mut cold, true); cold.frame(); - let mut wrong = Vec::new(); - for (i, (&w, &c)) in ids.iter().zip(&cold_ids).enumerate() { - let (got, want) = (warm.region(&w), cold.region(&c)); - if got != want { - wrong.push(format!("widget {i}: warm {got:?} cold {want:?}")); - } - } - assert!(wrong.is_empty(), "{}", wrong.join("\n")); + assert_same_regions(&warm, &ids, &cold, &cold_ids); } const PARAGRAPH: &str = "Wrapping shapes one source into as many lines as the \ diff --git a/tests/chain_cost.rs b/tests/chain_cost.rs index 4dc27bd..f7f5e13 100644 --- a/tests/chain_cost.rs +++ b/tests/chain_cost.rs @@ -11,8 +11,6 @@ //! The instances are two pixels wide so that vertex work dominates; a chain //! walk that does not show up against small quads will not show up against //! anything. -//! -//! The instance is leaked deliberately, for the reason `draw_cost.rs` gives. use iris::prelude::*; use iris_core::{ @@ -21,6 +19,9 @@ use iris_core::{ }; use wgpu::{Color as GpuColor, *}; +#[path = "gpu/mod.rs"] +mod gpu; + const SIZE: u32 = 1024; const INSTANCES: usize = 200_000; const FRAMES: u32 = 20; @@ -29,18 +30,7 @@ const FRAMES: u32 = 20; const BATCHES: u32 = 8; fn gpu() -> Option<(Device, Queue, f32)> { - let all = Instance::new(InstanceDescriptor::new_without_display_handle()); - let instance = match pollster::block_on(all.request_adapter(&RequestAdapterOptions::default())) - { - Ok(_) => all, - Err(_) => Instance::new(InstanceDescriptor { - backends: Backends::GL, - ..InstanceDescriptor::new_without_display_handle() - }), - }; - let instance: &'static Instance = Box::leak(Box::new(instance)); - let adapter = - pollster::block_on(instance.request_adapter(&RequestAdapterOptions::default())).ok()?; + let adapter = gpu::adapter()?; if !adapter.features().contains(Features::TIMESTAMP_QUERY) { println!("no timestamp queries on {:?}", adapter.get_info().name); return None; @@ -55,20 +45,6 @@ fn gpu() -> Option<(Device, Queue, f32)> { Some((device, queue, period)) } -fn config(format: TextureFormat) -> SurfaceConfiguration { - SurfaceConfiguration { - usage: TextureUsages::RENDER_ATTACHMENT, - format, - color_space: SurfaceColorSpace::Auto, - width: SIZE, - height: SIZE, - present_mode: PresentMode::Fifo, - desired_maximum_frame_latency: 2, - alpha_mode: CompositeAlphaMode::Auto, - view_formats: vec![], - } -} - /// A chain `depth` slots long, and instances that all resolve through its end. fn fill(ui: &mut UiData, render: &mut UiRenderState, depth: usize) { let kind = ui.primitives.kind::(); @@ -103,7 +79,7 @@ fn fill(ui: &mut UiData, render: &mut UiRenderState, depth: usize) { /// Nanoseconds the pass took on the GPU, best of `BATCHES`. fn pass_cost(device: &Device, queue: &Queue, period: f32, depth: usize) -> f64 { let format = TextureFormat::Bgra8Unorm; - let mut node = UiRenderNode::new(device, &config(format)); + let mut node = UiRenderNode::new(device, &gpu::config(format, SIZE)); let mut ui = UiData::default(); let mut render = UiRenderState::new(); fill(&mut ui, &mut render, depth); diff --git a/tests/draw_cost.rs b/tests/draw_cost.rs index 589e8cf..ef25031 100644 --- a/tests/draw_cost.rs +++ b/tests/draw_cost.rs @@ -13,10 +13,6 @@ //! That is how `PrimitiveRender` was measured against a match in the renderer: //! 6 instructions per list drawn, against the ~5,400 wgpu spends recording //! one. -//! -//! The instance is leaked deliberately. A Vulkan loader may unload the driver -//! when the last one drops, which can fault as a thread that used it exits -- -//! and every test runs on a spawned thread. use std::time::Instant; @@ -27,6 +23,9 @@ use iris_core::{ }; use wgpu::{Color as GpuColor, *}; +#[path = "gpu/mod.rs"] +mod gpu; + const SIZE: u32 = 1024; const FRAMES: u32 = 200; /// Reported as the best of this many batches, since the mean moves by more @@ -34,39 +33,11 @@ const FRAMES: u32 = 200; const BATCHES: u32 = 8; fn gpu() -> Option<(Device, Queue)> { - // Probed rather than assumed: there may be no Vulkan adapter, and GL is - // what is left when there is not. - let all = Instance::new(InstanceDescriptor::new_without_display_handle()); - let instance = match pollster::block_on(all.request_adapter(&RequestAdapterOptions::default())) - { - Ok(_) => all, - Err(_) => Instance::new(InstanceDescriptor { - backends: Backends::GL, - ..InstanceDescriptor::new_without_display_handle() - }), - }; - // Leaked rather than dropped: see the note at the top of the file. - let instance: &'static Instance = Box::leak(Box::new(instance)); - let adapter = - pollster::block_on(instance.request_adapter(&RequestAdapterOptions::default())).ok()?; + let adapter = gpu::adapter()?; println!("adapter: {:?}", adapter.get_info()); pollster::block_on(adapter.request_device(&DeviceDescriptor::default())).ok() } -fn config(format: TextureFormat) -> SurfaceConfiguration { - SurfaceConfiguration { - usage: TextureUsages::RENDER_ATTACHMENT, - format, - color_space: SurfaceColorSpace::Auto, - width: SIZE, - height: SIZE, - present_mode: PresentMode::Fifo, - desired_maximum_frame_latency: 2, - alpha_mode: CompositeAlphaMode::Auto, - view_formats: vec![], - } -} - /// Every layer draws all three primitives, so the renderer takes a different /// path for each list it walks -- which is the case a single-primitive layer /// would never exercise. Images are bound per instance, so there are few. @@ -136,7 +107,7 @@ fn fill( fn frame_cost(device: &Device, queue: &Queue, layers: usize, per_layer: usize) -> f64 { let format = TextureFormat::Bgra8Unorm; - let mut node = UiRenderNode::new(device, &config(format)); + let mut node = UiRenderNode::new(device, &gpu::config(format, SIZE)); let mut ui = UiData::default(); let mut render = UiRenderState::new(); let _handles = fill(&mut ui, &mut render, layers, per_layer); diff --git a/tests/generated.rs b/tests/generated.rs index 133e6c7..6dfdd87 100644 --- a/tests/generated.rs +++ b/tests/generated.rs @@ -25,7 +25,7 @@ fn depth() -> usize { env("IRIS_GENERATED_DEPTH", 4) } -/// The seeds the ordinary tests take. Seven that have never failed; 86, +/// The seeds the ordinary tests take. Eight that have never failed; 86, /// which a `Scroll` fixed point once settled differently on; and 20, which /// caught a locally redrawn widget being placed twice in the box its parent /// had already placed it in. @@ -104,7 +104,7 @@ fn adding_and_removing_span_children_lands_where_growing_it_that_way_would() { } #[test] -#[ignore = "as many seeds as it is asked for, rather than the nine the others check"] +#[ignore = "as many seeds as it is asked for, rather than the ten the others check"] fn a_long_run_of_seeds_agrees() { let depth = depth(); let seeds: Vec = match std::env::var("IRIS_GENERATED_SEED") diff --git a/tests/gpu/mod.rs b/tests/gpu/mod.rs new file mode 100644 index 0000000..ebf42ef --- /dev/null +++ b/tests/gpu/mod.rs @@ -0,0 +1,40 @@ +//! The adapter and the surface configuration the GPU measurement rigs share, +//! so the two cannot probe for a device in two different ways. + +use wgpu::*; + +/// An adapter on whatever this machine has, or `None` where there is none. +/// +/// Probed rather than assumed: there may be no Vulkan adapter, and GL is what +/// is left when there is not. +/// +/// The instance is leaked deliberately. A Vulkan loader may unload the driver +/// when the last one drops, which can fault as a thread that used it exits -- +/// and every test runs on a spawned thread. +pub fn adapter() -> Option { + let all = Instance::new(InstanceDescriptor::new_without_display_handle()); + let instance = match pollster::block_on(all.request_adapter(&RequestAdapterOptions::default())) + { + Ok(_) => all, + Err(_) => Instance::new(InstanceDescriptor { + backends: Backends::GL, + ..InstanceDescriptor::new_without_display_handle() + }), + }; + let instance: &'static Instance = Box::leak(Box::new(instance)); + pollster::block_on(instance.request_adapter(&RequestAdapterOptions::default())).ok() +} + +pub fn config(format: TextureFormat, size: u32) -> SurfaceConfiguration { + SurfaceConfiguration { + usage: TextureUsages::RENDER_ATTACHMENT, + format, + color_space: SurfaceColorSpace::Auto, + width: size, + height: size, + present_mode: PresentMode::Fifo, + desired_maximum_frame_latency: 2, + alpha_mode: CompositeAlphaMode::Auto, + view_formats: vec![], + } +} diff --git a/tests/layout_diagnostics.rs b/tests/layout_diagnostics.rs index 7e56d59..f7b2293 100644 --- a/tests/layout_diagnostics.rs +++ b/tests/layout_diagnostics.rs @@ -219,7 +219,6 @@ fn layout_cost() { #[cfg(feature = "layout-diagnostics")] let _ = iris::core::layout_diagnostics::take(); run("cold", 1, &mut harness, |_, _| {}); - drop(tree); } if selected("repaint") { @@ -275,6 +274,5 @@ fn layout_cost() { run("resize", frames, &mut harness, |harness, frame| { harness.resize((OUTPUT.0 - ((frame + 1) % 2) as f32 * 8.0, OUTPUT.1)); }); - drop(tree); } } diff --git a/tests/trace_unsettled.rs b/tests/trace_unsettled.rs index 240f4ff..7519f2c 100644 --- a/tests/trace_unsettled.rs +++ b/tests/trace_unsettled.rs @@ -1,5 +1,5 @@ -//! 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. +//! Traces the four-widget trees in `unsettled.rs`, to see what box their text +//! is actually drawn in on a first frame against a settled one. #![cfg(feature = "layout-diagnostics")] @@ -9,30 +9,25 @@ 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 = wrapped.width(76).add(&mut h.rsc); - let aligned = sized; + let wrapped = wtext("Wrapping shapes") + .size(16) + .wrap(true) + .width(76) + .add(&mut h.rsc); h.rsc .widgets_mut() - .set_alignment(sized, Axis::X, AxisAlign::POS); + .set_alignment(wrapped, Axis::X, AxisAlign::POS); h.rsc .widgets_mut() - .set_alignment(sized, Axis::Y, AxisAlign::POS); + .set_alignment(wrapped, Axis::Y, AxisAlign::POS); let stack = Stack { - children: vec![plain.add_strong(&mut h.rsc), aligned.add_strong(&mut h.rsc)], + children: vec![plain.add_strong(&mut h.rsc), wrapped.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(), - ] + vec![plain.id(), wrapped.id(), stack.id(), root.id()] } fn dump(label: &str, report: &diag::Report, text: WidgetId) { @@ -93,23 +88,14 @@ fn what_box_the_text_is_drawn_in() { fn plant_fixed(h: &mut Harness) -> Vec { 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 = text; h.rsc .widgets_mut() .set_alignment(text, Axis::X, AxisAlign::NEG); - let inner = (aligned,).span(Dir::RIGHT).add(&mut h.rsc); - let sized = inner.sized((189, 176)).add(&mut h.rsc); + let inner = (text,).span(Dir::RIGHT).sized((189, 176)).add(&mut h.rsc); let filler = rect(Color::RED).add(&mut h.rsc); - let root = (filler, sized).span(Dir::RIGHT).add(&mut h.rsc); + let root = (filler, inner).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(), - ] + vec![text.id(), inner.id(), filler.id(), root.id()] } #[test]