Package swingtree.api

Class Layout.ForFlowLayout

java.lang.Object
swingtree.api.Layout.ForFlowLayout
All Implemented Interfaces:
Layout
Enclosing interface:
Layout

@Immutable public static final class Layout.ForFlowLayout extends Object implements Layout
An immutable Layout implementation that configures and installs a ResponsiveGridFlowLayout onto a component. It holds:
  • Alignment (align) — the horizontal alignment of components within each row of the flow (left, center, right, leading, or trailing).
  • Horizontal gap (hgap) — the pixel spacing between components in the same row.
  • Vertical gap (vgap) — the pixel spacing between rows.
  • Per-child FlowCell constraints (childConstraints) — a sorted Association mapping child indices (Integer) to FlowCells that are pushed onto the component's direct children. Unlike a positional tuple, the association is sparse: you only need to include entries for the children you actually want to configure. Each FlowCell carries a responsive span policy (see UILayoutConstants.AUTO_SPAN(Configurator)) that the ResponsiveGridFlowLayout queries on every layout pass to determine how many grid columns a child should occupy for the current parent size.

The child-constraint tuple is the key to building fully reactive responsive layouts. With the static UI.AUTO_SPAN() approach every child's span policy is fixed at the time the component is added. When child constraints need to change at runtime (e.g. the number of columns depends on application state), wrap a Layout.ForFlowLayout in a Var and pass it to UIForAnySwing.withLayout(sprouts.Val):


      import static swingtree.UI.*;
      // ...
      Var<Layout> layout = Var.of(
          Layout.flow( AUTO_SPAN(it -> it.small(12).medium(6)),
                       AUTO_SPAN(it -> it.small(12).medium(6)) )
      );

      UI.panel()
        .withLayout(layout)
        .add( label("A") )
        .add( label("B") );

      // Later: swap to a single full-width column for both children:
      layout.set( Layout.flow( AUTO_SPAN(12), AUTO_SPAN(12) ) );
  
Changing the layout property triggers a style re-evaluation, which calls installFor(JComponent), which re-pushes the updated FlowCells as client properties onto the children so that the next layout pass picks them up.

Instances are created via the Layout.flow() family of factory methods and are further configured through the fluent with* wither methods.

  • Method Details

    • withAlignment

      public Layout.ForFlowLayout withAlignment(UI.HorizontalAlignment align)
      Returns a new Layout.ForFlowLayout with the given horizontal alignment and all other properties copied unchanged.
      Parameters:
      align - The new horizontal alignment for the flow.
      Returns:
      A new Layout.ForFlowLayout with the updated alignment.
    • withHorizontalGap

      public Layout.ForFlowLayout withHorizontalGap(int hgap)
      Returns a new Layout.ForFlowLayout with the given horizontal gap size and all other properties copied unchanged.
      Parameters:
      hgap - The new horizontal gap between components, in pixels.
      Returns:
      A new Layout.ForFlowLayout with the updated horizontal gap.
    • withVerticalGap

      public Layout.ForFlowLayout withVerticalGap(int vgap)
      Returns a new Layout.ForFlowLayout with the given vertical gap size and all other properties copied unchanged.
      Parameters:
      vgap - The new vertical gap between component rows, in pixels.
      Returns:
      A new Layout.ForFlowLayout with the updated vertical gap.
    • withChildConstraints

      public Layout.ForFlowLayout withChildConstraints(sprouts.Association<Integer,FlowCell> childConstraints)
      Returns a new Layout.ForFlowLayout whose per-child FlowCell constraints are replaced by the supplied sorted Association.

      Keys are child indices (0 = first child, 1 = second, etc.); the association is sparse, so you only need to include entries for children you actually want to configure. Children whose index has no entry keep whatever FlowCell they already have. An empty association means no constraints are stored in this layout object; any AddConstraint client properties previously pushed to children by an earlier installFor call remain on those children until explicitly overwritten.
      The intended way of creating FlowCells is by using UILayoutConstants.AUTO_SPAN(Configurator)!
      An important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any span policies defined, it will always default to spanning 12 cells at all parent size categories!

      Parameters:
      childConstraints - The positional FlowCell constraints for the children.
      Returns:
      A new Layout.ForFlowLayout with the updated child constraints.
    • withChildConstraints

      public Layout.ForFlowLayout withChildConstraints(FlowCell... childConstraints)
      Returns a new Layout.ForFlowLayout whose per-child FlowCell constraints are replaced by the supplied varargs array.

      The constraints are mapped positionally to the component's children: the first argument applies to the first child, the second to the second, and so on. Passing an empty array stores no constraints in this layout object; any AddConstraint client properties previously pushed to children by an earlier installFor call remain on those children until explicitly overwritten.

      FlowCell instances are most conveniently created via UILayoutConstants.AUTO_SPAN(Configurator):

      
            import static swingtree.UI.*;
            // ...
            Layout.flow()
                  .withChildConstraints(
                      AUTO_SPAN( it -> it.small(12).medium(6) ),
                      AUTO_SPAN( it -> it.small(12).medium(6) )
                  )
        
      The intended way of creating FlowCells is through the UILayoutConstants.AUTO_SPAN(Configurator) factory method!
      An important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any size specific span policies defined, it will always default to spanning 12 cells at all parent size categories!
      Parameters:
      childConstraints - The FlowCell constraints to apply to the component's children in child-index order.
      Returns:
      A new Layout.ForFlowLayout with the updated child constraints.
    • withChildConstraint

      public Layout.ForFlowLayout withChildConstraint(int index, FlowCell childConstraint)
      Returns a new Layout.ForFlowLayout with the FlowCell at the given child index replaced by the supplied value. All other child constraints and all other properties are copied unchanged. The intended way of creating FlowCells is through the UILayoutConstants.AUTO_SPAN(Configurator) factory method!

      Because the underlying storage is a sparse Association, no padding is needed: the constraint is stored at exactly index, regardless of whether lower indices have entries.
      Another important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any size specific span policies defined, it will always default to spanning 12 cells at all parent size categories!

      Parameters:
      index - The zero-based index of the child whose constraint to update.
      childConstraint - The new FlowCell for the child at index.
      Returns:
      A new Layout.ForFlowLayout with the updated child constraint at index.
      Throws:
      IndexOutOfBoundsException - if index is negative.
    • withChildConstraint

      public Layout.ForFlowLayout withChildConstraint(int index, Configurator<FlowCellConf> cellConfig)
      Returns a new Layout.ForFlowLayout with the FlowCell at the given child index replaced by one built from the supplied Configurator lambda. The lambda receives a FlowCellConf and returns the configured version, matching exactly the API of UILayoutConstants.AUTO_SPAN(Configurator):
      
            Layout.flow()
                  .withChildConstraint(0, it -> it.small(12).medium(6).large(4))
                  .withChildConstraint(1, it -> it.small(12).medium(6).large(8))
        
      The intended way of creating FlowCells is through the UILayoutConstants.AUTO_SPAN(Configurator) factory method!
      An important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any size specific span policies defined, it will always default to spanning 12 cells at all parent size categories!
      Parameters:
      index - The zero-based index of the child whose constraint to update.
      cellConfig - A Configurator that configures the FlowCellConf for the child's responsive span policy.
      Returns:
      A new Layout.ForFlowLayout with the updated child constraint at index.
      Throws:
      IndexOutOfBoundsException - if index is negative.
    • withAddedChildConstraint

      public Layout.ForFlowLayout withAddedChildConstraint(FlowCell childConstraint)
      Returns a new Layout.ForFlowLayout with the supplied FlowCell appended to the end of the existing child-constraint tuple. This is a convenient alternative to withChildConstraints(FlowCell...) when building up constraints one at a time:
      
            import static swingtree.UI.*;
            // ...
            Layout.flow()
                  .withAddedChildConstraint( AUTO_SPAN(it -> it.small(12).medium(6)) )
                  .withAddedChildConstraint( AUTO_SPAN(it -> it.small(12).medium(6)) )
        
      The intended way of creating FlowCells is through the UILayoutConstants.AUTO_SPAN(Configurator) factory method!
      An important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any size specific span policies defined, it will always default to spanning 12 cells at all parent size categories!
      Parameters:
      childConstraint - The FlowCell to append as the next child constraint.
      Returns:
      A new Layout.ForFlowLayout with the constraint appended.
    • withAddedChildConstraint

      public Layout.ForFlowLayout withAddedChildConstraint(Configurator<FlowCellConf> cellConfig)
      Returns a new Layout.ForFlowLayout with a FlowCell built from the supplied Configurator lambda appended to the end of the existing child-constraint tuple. The lambda receives a FlowCellConf and returns the configured version, matching exactly the API of UILayoutConstants.AUTO_SPAN(Configurator):
      
            Layout.flow()
                  .withAddedChildConstraint( it -> it.small(12).medium(6) )
                  .withAddedChildConstraint( it -> it.small(12).medium(6) )
        
      The intended way of creating FlowCells is through the UILayoutConstants.AUTO_SPAN(Configurator) factory method!
      An important edge case to consider when writing a responsive flow layout:
      If a FlowCell is passed to the responsive flow layout without any size specific span policies defined, it will always default to spanning 12 cells at all parent size categories!
      Parameters:
      cellConfig - A Configurator that configures the FlowCellConf for the appended child's responsive span policy.
      Returns:
      A new Layout.ForFlowLayout with the constraint appended.
    • hashCode

      public int hashCode()
      Specified by:
      hashCode in interface Layout
      Overrides:
      hashCode in class Object
      Returns:
      A hash code value for this layout.
    • equals

      public boolean equals(@Nullable Object o)
      Specified by:
      equals in interface Layout
      Overrides:
      equals in class Object
      Parameters:
      o - The object to compare this layout to.
      Returns:
      true if the supplied object is a layout that is equal to this layout, false otherwise.
    • installFor

      public void installFor(JComponent component)
      Installs a ResponsiveGridFlowLayout onto the supplied component and applies all constraints stored in this configuration.

      The installation proceeds in two phases:

      1. Layout manager — if no ResponsiveGridFlowLayout is currently installed, a new one is created with the stored alignment and gap settings. If one is already installed, only the properties that have changed are updated in-place and JComponent.revalidate() is called.
      2. Child constraints — if the child-constraint tuple is non-empty, each stored FlowCell is written as a AddConstraint client property onto the corresponding direct child (using the same key that ResponsiveGridFlowLayout.addLayoutComponent(java.lang.String, java.awt.Component) uses, so the layout manager picks them up on the next layout pass). Only entries that differ from the currently stored value are written, and JComponent.revalidate() is called exactly once at the end if anything changed.
      Specified by:
      installFor in interface Layout
      Parameters:
      component - The component to install the ResponsiveGridFlowLayout for.
    • toString

      public String toString()
      Overrides:
      toString in class Object