Class Wrap


public class Wrap extends Container<Wrap>
Places children one after another along a line in reading order, and starts a new line below when the next child does not fit in what is left of the width: the layout for a set of tags, chips, filters or buttons whose number or length is not known when the window is designed. Each line is a run.

A run is laid out the way a Row lays out its children: gap between neighbours, mainAlignment for the room left at the end of the run, and crossAlignment for where a child sits within the height of its run, which is the height of the run's tallest child. So a wrap whose children all fit on one line places them where a row with the same gap and alignments would, and it is the width, and only the width, that decides where a new run starts. Runs stack top to bottom with runGap between them. In a right-to-left subtree (LayoutDirection) a run starts at the right edge and fills leftwards, and the runs still go down.

What it measures to. Every child is measured once, against the width the wrap is given and never against what is left of a run, so a child's size does not depend on where it lands. The wrap is as wide as its widest run and as tall as its runs and the gaps between them. With no bound on the width, which is what Scene.pack() and a horizontally scrolling parent give, everything is one run, as wide as a row of the same children. A child wider than the width on its own takes a run of its own and is given at most that width, so whether it wraps its own text, ellipsises or overflows is the child's measure to decide and not the wrap's.

No child is flexible here. A run has no leftover to share out: what one run leaves over is the room the next child did not fit into, and it belongs to mainAlignment. So an Expanded is refused when it is added, rather than accepted and silently laid out as the widget it wraps; a fixed gutter between two children is a SizedBox.

A wrap draws nothing, clips nothing and describes nothing to an assistive technology, so it publishes no node of its own and its children take its place. Their reading order, and the order Tab visits them in, is the order they were added in, run after run, in both directions: a right-to-left subtree moves the boxes and not the order.

  • Constructor Details

    • Wrap

      public Wrap()
      An empty wrap, with no gap on either axis, its runs against the edge reading starts from.
  • Method Details

    • gap

      public Wrap gap(float newGap)
      Space between neighbours on a run, in logical points: the gutter a Row's Flex.gap is, never before the first child of a run or after its last. Negative values clamp to 0. UI thread only.
      Parameters:
      newGap - the gutter along a run
      Returns:
      this wrap
      Throws:
      IllegalArgumentException - when NaN or infinite
    • runGap

      public Wrap runGap(float newGap)
      Space between one run and the next, in logical points, never above the first run or below the last; a wrap that fits on one run shows none of it. Negative values clamp to 0. UI thread only.
      Parameters:
      newGap - the gutter between runs
      Returns:
      this wrap
      Throws:
      IllegalArgumentException - when NaN or infinite
    • gapsSilently

      protected final void gapsSilently(float newGap, float newRunGap)
      Sets both gutters without requesting a layout pass: the measure-path form, for a wrap whose gutters follow resolved size tokens and are pushed from its own onMeasure, as Flex's silent gap is. Safe there and only there: the caller is already inside the pass that consumes them. Everything else uses gap(float) and runGap(float), and this refuses and clamps what they do.
      Parameters:
      newGap - the gutter along a run
      newRunGap - the gutter between runs
      Throws:
      IllegalArgumentException - when either is NaN or infinite
    • mainAlignment

      public Wrap mainAlignment(Flex.MainAlignment alignment)
      Where the children of each run sit along it when the run is narrower than the wrap, run by run, on the two vocabularies Flex.MainAlignment describes: START, END and SPACE_BETWEEN follow the reading direction, and LEFT and RIGHT keep naming a side of the box whichever way the subtree reads. SPACE_BETWEEN spreads every run, the last one included, and puts a run of one child where reading starts. The default is START. UI thread only.
      Parameters:
      alignment - the placement of each run's children along it
      Returns:
      this wrap
    • crossAlignment

      public Wrap crossAlignment(Flex.CrossAlignment alignment)
      Where a child sits within the height of its run, which is the height of the run's tallest child. START, CENTER and END place the box, and do not turn around in a right-to-left subtree because the axis is vertical. BASELINE lines up the text of a run's children, shifting each one down inside its run and never out of it, the clamp a Row applies inside its own height. STRETCH makes every child of a run as tall as the run, and costs a second measure in every pass of each child shorter than its run, because the height it is stretched to is known only once the run is formed. The default is START. UI thread only.
      Parameters:
      alignment - the placement of a child within its run
      Returns:
      this wrap
    • add

      public void add(Widget<?> child)
      Appends a child (UI thread only).
      Overrides:
      add in class Container<Wrap>
      Parameters:
      child - the child to append
      Throws:
      IllegalArgumentException - when child is an Expanded, which has no leftover to take in a wrap
    • add

      public void add(int index, Widget<?> child)
      Inserts a child at a position in Widget.children() (UI thread only).
      Overrides:
      add in class Container<Wrap>
      Parameters:
      index - where the child goes, in [0, children().size()]
      child - the child to insert; never null
      Throws:
      IllegalArgumentException - when child is an Expanded, which has no leftover to take in a wrap
    • onMeasure

      protected Size onMeasure(Constraints constraints)
      Description copied from class: Widget
      Reports the size this widget wants within constraints. Called once per layout pass, and the result is cached against the constraints and the resolved axes (size step, layout direction, locale), so it must be a pure function of them and of this widget's own state.

      Resolve the ControlSize and the LayoutDirection once each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, and I18n.locale() answers it wherever text is resolved.

      Specified by:
      onMeasure in class Widget<Wrap>
    • onLayout

      protected void onLayout()
      Description copied from class: Widget
      Containers position children here (measure + Widget.layoutBox(float, float, float, float) per child).
      Overrides:
      onLayout in class Widget<Wrap>