Package limn.scene

Enum Class ControlSize

All Implemented Interfaces:
Serializable, Comparable<ControlSize>, Constable

public enum ControlSize extends Enum<ControlSize>
The size step of a control: a deliberate, hand-tuned design axis, not a scale factor and not a DPI setting (that is Canvas.contentScale(), applied downstream in the backend; the two multiply, in that order, and must never be conflated).

Per step, type, control heights and spacing move on three different hand-authored ramps, while strokes (borders, focus rings and their gaps, hairline separators, check-mark strokes, carets) keep the same thickness at every step. Nothing anywhere is base * k(step).

This enum is the axis only. It carries no numbers, so the toolkit can own it without knowing anything about a theme, which is what lets a raw Row act as a size scope for the components inside it. What a step means lives with the design tokens in the components layer (limn.components.SizeTokens, reached through Theme.tokensFor(widget)).

The coexistence contract

A widget's step is inherited down the tree: its own declared value, else the nearest declaring ancestor's, else its scene's default, else its host's, else processDefault().

Several steps therefore coexist in one window, in one frame: a SMALL toolbar above a MEDIUM form beside a LARGE dialog is three scopes in one tree, resolved independently, laid out in a single pass. Any subtree overrides its ancestors, and a subtree that declares its own step is untouched when an ancestor's changes: Widget.measure(limn.scene.Constraints) keys its cache on the resolved step, so a container's change re-measures exactly the descendants whose step actually changed.

A row that mixes steps and carries text needs a baseline, not a box. CrossAlignment.CENTER aligns boxes, and the baseline offset between steps is a function of the type ramp that no choice of control heights cancels: adjacent steps sit up to 0.69 pt apart, the full ramp up to 2.73 pt. Use Flex.CrossAlignment.BASELINE there, CENTER otherwise. START aligns box tops exactly, but leaves the same baseline spread.

Never read this in a constructor

Widget.add(limn.scene.Widget) assigns the child's parent after the child is fully constructed, so new Button("OK") runs with no parent and resolves to the process default whatever its eventual parent declares. There is no reparent hook (Widget.onAttached() fires only on the null -> scene edge), so the usual builder order (toolbar.setControlSize(SMALL); toolbar.add(button);) never fires anything for the button. A step captured at construction is permanently wrong with no path to recovery.

Read it in onMeasure, onPaint, onLayout or an event handler, where the tree is complete, and resolve it once per pass into a local: two resolutions that disagree inside one component route clicks to the wrong segment, row or field.

Density floor

The height floor is 24 pt at XSMALL, so no control on the ramp needs a pointer target wider than its painted box and input dispatch is untouched. XSMALL is 0.750 of MEDIUM, a compact step, not a miniature one. Where an axis would fall below the floor it is clamped to Strokes.MIN_HIT_TARGET.
See Also:
  • Enum Constant Details

    • XSMALL

      public static final ControlSize XSMALL
      Dense: property inspectors, data-grid rows, packed toolbars.
    • SMALL

      public static final ControlSize SMALL
      Compact forms and toolbars.
    • MEDIUM

      public static final ControlSize MEDIUM
      The default. Every existing Limn UI renders here.
    • LARGE

      public static final ControlSize LARGE
      Primary actions, settings dialogs, low-density surfaces.
    • XLARGE

      public static final ControlSize XLARGE
      Hero and onboarding surfaces. Every component honours it; there is no clamp.
  • Method Details

    • values

      public static ControlSize[] values()
      Returns an array containing the constants of this enum class, in the order they are declared.
      Returns:
      an array containing the constants of this enum class, in the order they are declared
    • valueOf

      public static ControlSize valueOf(String name)
      Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)
      Parameters:
      name - the name of the enum constant to be returned.
      Returns:
      the enum constant with the specified name
      Throws:
      IllegalArgumentException - if this enum class has no constant with the specified name
      NullPointerException - if the argument is null
    • processDefault

      public static ControlSize processDefault()
      Returns:
      the step used where nothing in the tree and no scene declares one
    • setProcessDefault

      public static void setProcessDefault(ControlSize size)
      Sets the process-wide fallback step: the root of the inheritance chain, and the app-level "compact mode" switch. Every live scene re-measures, overlays included and unbound scenes included; widgets and scenes that declare their own step are unaffected. No-op when unchanged. UI thread only.
    • addChangeListener

      public static void addChangeListener(Runnable listener)
      Subscribes to process-default changes (idempotent per instance).
    • removeChangeListener

      public static void removeChangeListener(Runnable listener)
      Unsubscribes; no-op when it was never registered.