Raxol.UI.Layout.Engine (Raxol v2.6.0)

View Source

Core layout engine that translates the logical view structure into absolute positions.

This module is responsible for:

  • Calculating element positions based on available space
  • Resolving layout constraints
  • Managing the layout pipeline

Summary

Types

Terminal viewport dimensions in cells.

Input element. Every layout element has a :type atom; the rest of the shape is type-specific. Containers carry :children; leaves carry primitive fields like :text, :content, or :width/:height.

Intrinsic measurement -- the minimum space an element wants when laid out.

Output of apply_layout/3: a flat list of positioned elements where each carries absolute coordinates and dimensions. The renderer consumes these in order to produce cell tuples.

Available space for a layout pass. Origin (x, y) and extent (width, height) all in cell units relative to the viewport. Additional keys (e.g. :prepared_cache for the Pretext measurement cache) may also be present; only the four geometry keys are required.

Functions

Applies layout to a view, calculating absolute positions for all elements.

Looks up cached measurements for an element from the prepare phase.

Calculates the intrinsic dimensions (width, height) of an element.

Lays out a single element against space, prepending positioned elements to acc. Dispatches by :type; falls through to a logged warning for unknown types.

Types

dimensions()

@type dimensions() :: %{width: non_neg_integer(), height: non_neg_integer()}

Terminal viewport dimensions in cells.

element()

@type element() :: %{:type => atom(), optional(atom()) => any()}

Input element. Every layout element has a :type atom; the rest of the shape is type-specific. Containers carry :children; leaves carry primitive fields like :text, :content, or :width/:height.

Container types: :view, :panel, :row, :column, :grid, :flex, :css_grid, :responsive, :responsive_grid, :box, :split_pane, :absolute_layer.

Leaf types: :text, :label, :button, :text_input, :checkbox, :image, :divider, :spacer, :table.

measurement()

@type measurement() :: %{width: non_neg_integer(), height: non_neg_integer()}

Intrinsic measurement -- the minimum space an element wants when laid out.

positioned_element()

@type positioned_element() :: %{
  :type => atom(),
  :x => non_neg_integer(),
  :y => non_neg_integer(),
  optional(:width) => non_neg_integer(),
  optional(:height) => non_neg_integer(),
  optional(atom()) => any()
}

Output of apply_layout/3: a flat list of positioned elements where each carries absolute coordinates and dimensions. The renderer consumes these in order to produce cell tuples.

space()

@type space() :: %{
  :x => non_neg_integer(),
  :y => non_neg_integer(),
  :width => non_neg_integer(),
  :height => non_neg_integer(),
  optional(atom()) => any()
}

Available space for a layout pass. Origin (x, y) and extent (width, height) all in cell units relative to the viewport. Additional keys (e.g. :prepared_cache for the Pretext measurement cache) may also be present; only the four geometry keys are required.

Functions

apply_layout(view, dimensions, prepared_tree \\ nil)

@spec apply_layout(element(), dimensions(), Raxol.UI.Layout.PreparedElement.t() | nil) ::
  [
    positioned_element()
  ]

Applies layout to a view, calculating absolute positions for all elements.

Parameters

  • view - The view to calculate layout for
  • dimensions - Terminal dimensions %{width: w, height: h}
  • prepared_tree - Optional PreparedElement tree with cached text measurements from the prepare phase (Pretext two-phase architecture). When provided, measure_element will use cached measured_width / measured_height instead of re-calling TextMeasure.display_width.

Returns

A list of positioned elements with absolute coordinates.

lookup_in_cache(cache, type, content)

@spec lookup_in_cache(map() | nil, atom(), term()) ::
  {non_neg_integer(), non_neg_integer()} | nil

Looks up cached measurements for an element from the prepare phase.

The cache is built by build_measurement_cache/1 and lives on available_space.prepared_cache for the duration of apply_layout/3. Returns {width, height} if the entry exists, otherwise nil.

measure_element(element, available_space \\ %{})

@spec measure_element(element() | any(), map()) :: measurement()

Calculates the intrinsic dimensions (width, height) of an element.

This function determines the natural size of an element before layout constraints are applied. For containers, it might recursively measure children.

Parameters

  • element - The element map to measure.
  • available_space - Map providing context (e.g., max width).
  • Defaults to an empty map.

Returns

A map representing the dimensions: %{width: integer(), height: integer()}.

process_element(panel, space, acc)

@spec process_element(element() | any(), space(), [positioned_element()]) :: [
  positioned_element()
]

Lays out a single element against space, prepending positioned elements to acc. Dispatches by :type; falls through to a logged warning for unknown types.

Used internally by apply_layout/3 and by container layout modules (Containers, Flexbox, Grid, etc.) when recursing into children.