Skip to main content

SubView

Trait SubView 

Source
pub trait SubView {
    // Required methods
    fn measure(&self, proposal: ProposalSize) -> ViewDimensions;
    fn stretch_axis(&self) -> StretchAxis;
    fn priority(&self) -> i32;
}
Expand description

A proxy for querying child view sizes during layout.

This trait allows layout containers to negotiate with children by asking “if I propose this size, how big would you be?” multiple times with different proposals.

§Pure Functions

All methods are pure (take &self) with no side effects.

§Caching is the SubView’s responsibility, never the Layout’s

The Layout trait deliberately has no caching: containers probe their children freely with many proposals. Any measurement caching must therefore be owned by the SubView implementation itself (the leaf), not the container. Expensive measures — text shaping above all — must cache.

§Measurement is single-threaded by contract

Measuring runs on whichever thread drives layout, so a SubView is neither Send nor Sync and its cache may be a plain RefCell.

Measuring siblings on a worker pool was tried and removed. A container’s children number in the single digits and a cache-hit measure costs tens of nanoseconds, while a fork-join costs tens of microseconds — and it was paid by every container, including the majority with nothing to offload. Parallelism belongs where the work is genuinely large and batched (a renderer pre-shaping every visible text run for a frame), not inside the per-container measurement loop.

Required Methods§

Source

fn measure(&self, proposal: ProposalSize) -> ViewDimensions

Measure the child for a given proposal.

This method may be called multiple times with different proposals to probe the child’s flexibility:

  • ProposalSize::new(None, None) - ideal/intrinsic size
  • ProposalSize::new(Some(0.0), None) - minimum width
  • ProposalSize::new(Some(f32::INFINITY), None) - maximum width
  • ProposalSize::new(Some(200.0), None) - constrained width
§The three-point contract

Containers work out how far a child may shrink, and how far it wants to grow, from those first three answers, so on each axis they must satisfy min <= ideal <= max. Every extent is finite and non-negative, except a maximum, where f32::INFINITY means unbounded — that is how a view says it will take whatever it is offered.

Breaking this is not a local error: a minimum above the ideal makes a stack compress a child past a size it cannot take, and an ideal above the maximum makes it stretch one past a size it cannot take. Both surface as a misplaced layout somewhere else entirely.

Source

fn stretch_axis(&self) -> StretchAxis

Which axis (or axes) this view stretches to fill available space.

  • StretchAxis::None: Content-sized, uses intrinsic size
  • StretchAxis::Horizontal: Expands width only (e.g., TextField, Slider)
  • StretchAxis::Vertical: Expands height only
  • StretchAxis::Both: Greedy, fills all space (e.g., Spacer, Color)

Layout containers use this to distribute remaining space appropriately:

  • VStack checks stretches_vertical() for height distribution
  • HStack checks stretches_horizontal() for width distribution
Source

fn priority(&self) -> i32

Layout priority for space distribution.

Higher priority views are measured first and get space preference.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§