Drafter.Runtime.Renderer (drafter v0.3.1)

Copy Markdown View Source

Rendering pipeline for Drafter applications.

Converts a widget hierarchy into terminal output via the compositor. Stateless — no process state, no message passing.

Summary

Types

A rectangle in terminal cells, as carried through the render pipeline.

Functions

One compositor layer per visible widget in hierarchy.

Render one frame for app_module and return the hierarchy to reuse next frame.

Composite an already-built hierarchy and push the result to the compositor.

Composite the app, every screen on the screen stack, and any toasts, in that order.

Refresh each widget's cached state from its server and recompute preferred sizes.

Types

rect()

@type rect() :: %{
  x: integer(),
  y: integer(),
  width: non_neg_integer(),
  height: non_neg_integer()
}

A rectangle in terminal cells, as carried through the render pipeline.

Functions

create_widget_layers_from_hierarchy(hierarchy, rect, z_base \\ 0)

@spec create_widget_layers_from_hierarchy(map(), rect(), non_neg_integer()) :: [map()]

One compositor layer per visible widget in hierarchy.

Widgets listed in the hierarchy's :hidden_widgets set are skipped. z_base is added to each layer's z-index, so a screen's layers can be lifted above the app's. Default: 0. The rect argument is accepted for call-site symmetry and ignored; each layer is bounded by its own widget rect.

render_app(app_module, app_state, screen_rect, existing_hierarchy \\ nil)

@spec render_app(module(), term(), rect(), map() | nil) ::
  {:ok, map() | nil} | {:error, nil}

Render one frame for app_module and return the hierarchy to reuse next frame.

With screens pushed on the screen manager, the screens are rendered and existing_hierarchy is returned untouched. With toasts but no screens, the app's hierarchy is rebuilt first so the toast composites over it. Otherwise the app is rendered directly, reusing existing_hierarchy when the app state hash and layout are both unchanged.

Returns {:ok, hierarchy}, {:ok, nil} when the app's render/1 returned strips rather than a component tree, or {:error, nil} when it returned {:error, reason}.

render_hierarchy(hierarchy, screen_rect)

@spec render_hierarchy(map(), rect()) :: :ok

Composite an already-built hierarchy and push the result to the compositor.

Used on the fast path, when the app state and layout are unchanged and no widget tree needs rebuilding. Any pushed screens and toasts are composited on top.

render_screens_from_manager(screen_rect, app_module, app_state, existing_hierarchy)

@spec render_screens_from_manager(rect(), module(), term(), map() | nil) :: :ok

Composite the app, every screen on the screen stack, and any toasts, in that order.

existing_hierarchy supplies the app's base layers when it is not nil; otherwise the app is re-rendered to produce them. Note the argument order: screen_rect comes first here, unlike render_app/4.

update_hierarchy_preferred_sizes(hierarchy)

@spec update_hierarchy_preferred_sizes(map()) :: map()

Refresh each widget's cached state from its server and recompute preferred sizes.

Widgets whose entry carries no live pid are left alone, as is a widget whose server fails to answer — its previously cached state is kept.