Interface CssEmittingLayoutManager

All Superinterfaces:
LayoutManager
All Known Implementing Classes:
BorderLayout, BoxLayout, FlowLayout, GridBagLayout, GridLayout, GroupLayout

public interface CssEmittingLayoutManager extends LayoutManager
A LayoutManager that positions children by emitting CSS onto the container's peer <div> (and optionally onto each child) instead of the pixel setBounds arithmetic a desktop LayoutManager does — there is no synchronous child-size measurement in the browser to drive that arithmetic. This is the seam a migrator implements to teach the emulator a custom Swing layout; every built-in (FlowLayout, BorderLayout, BoxLayout, GridLayout, GridBagLayout, GroupLayout) is one of these.

Implement containerCss(Container); add childCss(Container, Component) only when children need per-item CSS. The framework drives layoutContainer(Container) for you — you never touch EHelper or a Vaadin Element:

// A two-column form: labels hug their content, fields absorb the rest.
public class TwoColumnLayout implements CssEmittingLayoutManager {
    public Map<String,String> containerCss(Container parent) {
        return Map.of("display", "grid",
                      "grid-template-columns", "auto 1fr",
                      "gap", "4px 8px");
    }
}
// parent.setLayout(new TwoColumnLayout());   // children flow into the grid

A container whose installed layout is not a CssEmittingLayoutManager — a hand-rolled pixel LayoutManager — can't be translated: Container.doLayout() WARNs once and falls back to a readable vertical stack (M1D_custom_layoutmanager).

Implementation details

Call order (contract). Within one layoutContainer(Container) pass containerCss(Container) runs exactly once, before any childCss(Container, Component) call. A layout whose per-child CSS is a byproduct of a whole-container analysis (GridBag track weights, GroupLayout bands) may compute in containerCss, stash the result, and read it back in childCss — GridBagLayout and GroupLayout do exactly this. A layout whose per-child CSS is already known at add time can instead write it eagerly from addLayoutComponent and skip childCss entirely — BorderLayout does that with grid-area.

Child sizing (D_layout_owns_child_sizing). A child's Component.setPreferredSize(Dimension) does not write width / height outright — it writes width: var(--emul-layout-w, Npx), and the parent layout rules on each axis by writing that variable from childCss(Container, Component): com.vaadin.swingbridge.surrogates.util.LayoutCss.sizingCss(layoutSizesWidth, layoutSizesHeight) builds the pair. Say true for an axis this layout sizes itself (the pref is ignored, as BorderLayout NORTH ignores the pref width), false to let the pref stand. A layout that returns neither variable leaves whatever the last layout wrote in place, so emit both for every child — sizingCss always does.

Map semantics. A returned map applies key-by-key: a value sets the property, null removes it, an absent key is left untouched — so a layout can clear a sibling layout's leftover keys without clobbering co-owned ones (a field surrogate's inline width). containerCss(Container) writes gate on the peer being a <div> (a non-Div peer gets an ERROR and no write); childCss(Container, Component) writes do not gate — a child is any element.

  • Method Details

    • containerCss

      Map<String,String> containerCss(Container parent)
      Container-wide CSS for parent's peer content element (its <div>).
      Returns:
      property→value map; a null value removes the property, an absent key is left untouched.
    • childCss

      default Map<String,String> childCss(Container parent, Component child)
      Per-child CSS for one child of parent; null (the default) means the child needs none. Called once per child per pass, after containerCss(Container) (see the call-order contract).
    • cssLayoutName

      default String cssLayoutName()
      Name used in the non-Div ERROR log for containerCss(Container) writes.
    • layoutContainer

      default void layoutContainer(Container parent)
      Specified by:
      layoutContainer in interface LayoutManager