Class LayoutCss

java.lang.Object
com.vaadin.swingbridge.surrogates.util.LayoutCss

public final class LayoutCss extends Object
Builders that translate AWT/Swing LayoutManager parameters into the container-wide CSS a Vaadin host element needs, plus applyContainerCss(Element, String, Map) which writes a built block onto that element. One-way build + apply — there is no round-trip back to a LayoutManager (layout is best-effort per R_best_effort_behaviour/R_layouts_close_enough), so this is deliberately not an S*Convert-shaped pair.

Shared by both modules in the SD_shelper_statics-allowed direction (:emulators → :surrogates): emulator LayoutManagers route their output through vaadinx.EHelper.applyContainerCss (a thin forwarder to applyContainerCss(Element, String, Map)); the surrogate ContainerMixin calls the builders directly. BoxLayout axis constants are referenced by literal int (that layout lives in :emulators, which :surrogates can't depend on); FlowLayout's constants are JDK-side and referenced by symbol.

Implementation details

Each grid/flex builder writes an explicit value for every key any sibling builder might have written, not just its own — a JPanel's default ctor installs FlowLayout (writing flex-wrap / align-items / justify-content / gap) and other layouts write grid-template-areas, so a later setLayout(...) that set only its own keys would inherit stale ones (a leftover flex-wrap: wrap wraps a BoxLayout column into several visual columns, a leftover named-areas template pins children into the wrong grid cells). The per-builder reset comments note only the layout-specific consequence.

  • Field Details

    • PREF_W_VAR

      public static final String PREF_W_VAR
      The custom property through which a child's preferred width reaches CSS, and through which its parent layout overrides it. See sizingCss(boolean, boolean) for the two-owner contract; D_layout_owns_child_sizing for why it exists.
      See Also:
    • PREF_H_VAR

      public static final String PREF_H_VAR
      Vertical counterpart of PREF_W_VAR.
      See Also:
    • AXIS_LAYOUT

      public static final String AXIS_LAYOUT
      The value a layout writes into PREF_W_VAR / PREF_H_VAR to take an axis over: auto restores the container's own stretch, which sizes the border box (where width: 100% overflows a content-box element by its border).
      See Also:
    • AXIS_PREF

      public static final String AXIS_PREF
      The value a layout writes to leave an axis to the child's preferred size. initial on a custom property is the guaranteed-invalid value, so the child's var(--emul-layout-w, <pref>px) falls back to the pref — which is what lets a layout express its whole policy in the variable and never touch width.
      See Also:
  • Method Details

    • applyContainerCss

      public static void applyContainerCss(com.vaadin.flow.dom.Element target, String layoutManagerName, Map<String,String> css)
      Apply a block of layout CSS to a container's host element. Gates on the element being a plain <div>: non-Div hosts get a SHelper.onUnsupportedPeerShape(String, String) ERROR log and no CSS is written — setting a LayoutManager on a surrogate whose element is, say, a <vaadin-button> would corrupt its rendering.

      null values remove the corresponding style property, mirroring the null → inherit from parent contract used elsewhere in the Vaadin-first style layer (see ComponentMixin.setBackground(Color) convention).

    • applyChildCss

      public static void applyChildCss(com.vaadin.flow.dom.Element target, Map<String,String> css)
      Apply per-child layout CSS to one child's element — the per-child leg of a CssEmittingLayoutManager pass. Unlike applyContainerCss(Element, String, Map) there is no <div> gate: a child is any element. null removes, absent key untouched (same key-by-key contract).
    • prefWidth

      public static String prefWidth(String fallback)
      Wrap a preferred width in the PREF_W_VAR indirection: the value a child writes to its own width, letting its parent layout override the axis without a write ordering between the two.

      null in, null out — so a caller whose hint is "no preference" (CssConvert.columnsToCssWidth(int) on zero columns) can pass it straight through to a setWidth that clears the property.

      Parameters:
      fallback - the CSS length the child prefers, e.g. "850px" or "calc(10ch + 2em)"
    • prefHeight

      public static String prefHeight(String fallback)
      Vertical counterpart of prefWidth(String).
    • sizingCss

      public static Map<String,String> sizingCss(boolean layoutSizesWidth, boolean layoutSizesHeight)
      The per-child half of D_layout_owns_child_sizing: which axes of one child the parent layout sizes itself, and which it leaves to the child's preferred size.

      A preferred size means nothing on its own — AWT's child never sizes itself, and layoutContainer decides per axis whether to consult, clamp or ignore the pref (BorderLayout NORTH takes the container's width and only the pref height; GridLayout ignores both). So the child writes the pref as width: var(--emul-layout-w, Npx) and each layout writes the two variables here, one per axis.

      Both variables are always written, initial included: custom properties inherit, so a child that left one unset would read its ancestor's value — a BorderLayout CENTER panel's auto would otherwise erase the pref widths of every descendant under an absolute-layout child. The @property … inherits: false registrations in emul/emulator-theme.css are the other half of that defence; this one holds without the stylesheet.

      Parameters:
      layoutSizesWidth - the layout drives the horizontal axis (pref width ignored)
      layoutSizesHeight - the layout drives the vertical axis (pref height ignored)
    • containerKeys

      public static List<String> containerKeys()
      The CONTAINER_KEYS union, for the drift guard in LayoutCssTest.
    • resetContainerCss

      public static void resetContainerCss(com.vaadin.flow.dom.Element target)
      Drop every container-side layout property from target — the undo for applyContainerCss(Element, String, Map), called when a container's LayoutManager is replaced or cleared.

      Why an undo is needed at all: AWT's setLayout only invalidates, so the new manager's container CSS does not land until validate() / revalidate(). That quirk is faithful and deliberately kept (see vaadinx.awt.FlowLayout#setAlignment) — but a browser makes the un-revalidated interval visible in a way Swing never does: the host keeps the old manager's display:flex while children added under the new manager already carry its grid-area, so the container renders scrambled rather than merely un-laid-out. Clearing the container side turns that interval into plain block flow — still stale, like Swing's, but coherent.

      Per-child CSS is deliberately left alone: grid-* properties are inert without a grid parent, and clearing them would fight GridBagLayout's deliberate retention of child width / height.

      Silent no-op on a non-<div> host — applyContainerCss(Element, String, Map) never wrote layout CSS there, so there is nothing to undo and no unsupported shape to report to report.

    • verticalFallbackCss

      public static Map<String,String> verticalFallbackCss()
      Container CSS for the custom-LayoutManager fallback: a readable vertical stack. Installed by Container.doLayout when a container's layout is a hand-rolled pixel LayoutManager the emulator can't translate (M1D_custom_layoutmanager). Stretch-fills the cross axis so children stay full-width and nothing clips; resets grid-template-areas so a prior grid layout's named cells don't pin children (leftover grid-template-columns/rows are inert under display:flex).
    • flowLayoutCss

      public static Map<String,String> flowLayoutCss(int align, int hgap, int vgap)
      Build the container-wide CSS for FlowLayout. align matches FlowLayout's int constants (FlowLayout.LEFT / CENTER / RIGHT / LEADING / TRAILING). LEADING/TRAILING map to flex-start/flex-end — the dir="rtl" attribute on the host flips them automatically per Swing's leading/trailing-under-RTL contract. Ports the emulator's existing FlowLayout.layoutContainer body factored by primitives so both layers (and JDK / emulator FlowLayout flavours) call the same builder.
    • boxLayoutCss

      public static Map<String,String> boxLayoutCss(int axis)
      Build the container-wide CSS for vaadinx.swing.BoxLayout. axis matches BoxLayout's int constants (X_AXIS=0 / Y_AXIS=1 / LINE_AXIS=2 / PAGE_AXIS=3). LINE_AXIS pins to row and PAGE_AXIS to column — full RTL flipping (row-reverse on dir="rtl") would require tracking orientation at layoutContainer time; pinned LTR per R_layouts_close_enough same-shape as BorderLayout's LINE_START / LINE_END caveat. No gap key — JDK BoxLayout has no inherent inter-component spacing; Box.createVerticalStrut / createGlue components carry that responsibility via their own per-element CSS. Constants referenced by literal int rather than by symbol — vaadinx.swing.BoxLayout sits in :emulators and :surrogates can't depend on it.
    • borderLayoutCss

      public static Map<String,String> borderLayoutCss(int hgap, int vgap)
      Build the container-wide CSS for BorderLayout. Per- child grid-area writes happen separately in the layout's addLayoutComponent (see :emulators.BorderLayout); this helper just handles the grid setup.
    • gridBagLayoutCss

      public static Map<String,String> gridBagLayoutCss(double[] columnWeights, double[] rowWeights)
      Build the container-wide CSS for vaadinx.awt.GridBagLayout. columnWeights and rowWeights carry the per-track weight, max-aggregated across each track's children — JDK GridBagLayout's "any non-zero weight in a column makes that column absorb extra space" rule. A non-zero weight maps to Nfr (normalised so the sum of fr units across tracks reads naturally — we just use the raw weight as the fr count, which preserves the relative-ratio contract); a zero weight maps to auto so the track sizes to its content. minmax(0, …) on fr tracks lets them shrink below intrinsic size when the grid is height-bounded — BorderLayout CENTER precedent.

      hgap/vgap write through gap (column-gap row-gap shorthand). JDK GridBagLayout has no hgap/vgap of its own — spacing comes from per-child Insets. We pin gap to 0 here; all spacing rides on per-child margin (insets) / padding (ipadx/ipady) writes from GridBagLayout.layoutContainer.

      Per-child grid-row/grid-column/justify-self/ align-self/margin/padding/min-* writes happen separately in the layout's applyChildConstraintsCss; this helper just handles the grid setup. Resets flex-era keys for the same reason borderLayoutCss does — JPanel's default ctor installs FlowLayout and a setLayout(GridBagLayout) follow-up would otherwise leave them behind.

    • gridLayoutCss

      public static Map<String,String> gridLayoutCss(int nrows, int ncols, int hgap, int vgap)
      Build the container-wide CSS for vaadinx.awt.GridLayout. nrows/ncols are the resolved grid dimensions — GridLayout fixes one dimension and derives the other from the live child count, so the emulator does that arithmetic and passes the final numbers here. All cells are equal: repeat(N, 1fr) on both axes, matching JDK GridLayout's "divide the container into equal-sized rectangles" contract. Children auto-place row-major (grid-auto-flow: row, the CSS default) which reproduces GridLayout's left-to-right, top-to-bottom fill without any per-child placement.

      align-items/justify-items: stretch makes each child fill its cell — GridLayout resizes every component to the cell size (unlike FlowLayout, which uses preferred sizes). hgap/vgap write through gap (row-gap column-gap shorthand: vgap is the space between rows, hgap between columns). Resets the flex-era keys and grid-template-areas per the class-doc reset rule.

      nrows/ncols are clamped to at least 1 by the caller so repeat(0, 1fr) — invalid CSS — can never be emitted for an empty container.

    • groupLayoutCss

      public static Map<String,String> groupLayoutCss(String colTemplate, String rowTemplate, int gapPx)
      Build the container-wide CSS for vaadinx.swing.GroupLayout (D_grouplayout). The emulator reconstructs a CSS grid from GroupLayout's two axis group-trees and passes the finished repeat/auto track templates here (colTemplate/rowTemplate), each a space-separated track list where content-sized tracks are auto and resizable tracks are minmax(0, 1fr).

      align-items/justify-items: start is the default cell anchoring — GroupLayout's LEADING alignment — with per-child align-self/justify-self overrides written by the emulator from each component's effective parallel-group alignment. align-content/justify-content: start keeps the whole track group top-left anchored (resetting any justify-content: center left over from a JPanel's default FlowLayout, which on a grid would center the tracks).

      gapPx is a single uniform inter-track gap approximating GroupLayout's per-gap spacing — GroupLayout's gaps don't map to grid tracks in the reconstruction (R_layouts_close_enough; exact per-gap sizing is the deferred pixel-accurate layout is out of scope permanently, D_pixel_layout_not_planned). grid-template-areas is cleared per the class-doc reset rule.