Package limn.scene

Enum Class LayoutDirection

java.lang.Object
java.lang.Enum<LayoutDirection>
limn.scene.LayoutDirection
All Implemented Interfaces:
Serializable, Comparable<LayoutDirection>, Constable

public enum LayoutDirection extends Enum<LayoutDirection>
The direction a subtree lays out in: an inherited design axis, not a transform and not a property of the locale.

Mirroring in this toolkit is a placement decision, taken during layout and paint by the widget that owns the coordinate. There is no mirror transform at the canvas root and there must never be one: a global flip would turn correctly shaped text into a mirror image needing a per-run un-flip, would flip every image and every video frame, and would put an inverse transform on the hot path of every hit test.

This enum is the axis only. It carries no numbers and no locale knowledge, so the toolkit can own it without knowing anything about text, which is what lets a raw Row act as a direction scope for the components inside it. It is the companion of ControlSize, resolved by the same chain, invalidated by its own epoch, and read under the same two rules.

The coexistence contract

A widget's direction 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().

LTR is the process default and mirroring is opt-in per subtree, which is what makes a Hebrew interface holding a left-to-right code editor, log pane, URL bar or JSON viewer expressible: each of those is a subtree that reads one way inside an interface that reads the other, and a direction derived from a process-wide locale could not say so. An application in Arabic writes one line at its scene root; a subtree that disagrees writes one more.

This is never read from the locale

Nothing in the toolkit consults I18n.locale() to decide a direction. Language and direction are different axes: a Hebrew subtree inside an English interface still shows English strings, it just lays them out right to left. forLocale(java.util.Locale) exists so an application can bridge the two at its own call site, typically once at startup; it is not called by the toolkit and must not be called from inside a widget, where it would smuggle the process locale back into the axis this enum exists to keep out of it.

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. A direction captured at construction is permanently wrong with no path to recovery, exactly as a captured ControlSize is.

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 onPaint put the caret on one side and the selection band on the other.

What a direction change does to a held value

A paragraph's base direction decides which bidi level a boundary neutral takes, which decides which run it extends, which decides which face measures it. A line of mixed content therefore measures a fraction of a point differently in the two directions. The amount is one face's disagreement about a space per neutral at the paragraph's edge — an interior neutral does not move at all — so it is small on any real line, and it is nonetheless enough to make a held ShapedText and a cached measurement both stale across a change — which is why ShapedText.matches(java.lang.String, limn.graphics.Font, limn.graphics.ShapedText.Direction, limn.graphics.TextRuler) takes a direction and why Widget.measure(limn.scene.Constraints) keys its cache on the resolved one.
See Also:
  • Enum Constant Details

    • LTR

      public static final LayoutDirection LTR
      Left to right: the default, and what every existing Limn UI renders as.
    • RTL

      public static final LayoutDirection RTL
      Right to left: Arabic, Hebrew, Persian, Urdu and the rest of the right-to-left scripts.
  • Method Details

    • values

      public static LayoutDirection[] 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 LayoutDirection 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
    • opposite

      public LayoutDirection opposite()
      Returns:
      the opposite direction; LTR.opposite() == RTL
    • isRightToLeft

      public boolean isRightToLeft()
      Returns:
      whether this is RTL, for the dir == RTL tests that fill widgets
    • processDefault

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

      public static void setProcessDefault(LayoutDirection direction)
      Sets the process-wide fallback direction: the root of the inheritance chain, and the one line an application that is entirely right to left writes at startup. Every live scene re-measures, overlays included and unbound scenes included; widgets and scenes that declare their own direction 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.
    • forLocale

      public static LayoutDirection forLocale(Locale locale)
      Maps a locale to the direction its script is normally written in: the bridge between I18n and this axis, offered so that an application can write LayoutDirection.setProcessDefault(LayoutDirection.forLocale(locale)) at startup instead of writing the same table itself.

      Nothing in the toolkit calls this, and a widget that calls it has reintroduced the process-wide locale as a source of direction, which is the one thing this axis exists to prevent. It is a function from a locale to a direction, at an application's call site, and a starting point rather than a policy: an application whose user has chosen a direction should honour that choice instead.

      The script is consulted first and the language only when the locale names no script, because a language can be written in either. Anything unrecognised is LTR, which is the same fallback the first-strong rule makes for text with no strong character.

      Parameters:
      locale - the locale to classify
      Returns:
      RTL when that locale's script is written right to left, else LTR
      Throws:
      NullPointerException - if locale is null