Drafter.WidgetHierarchy (drafter v0.3.2)

Copy Markdown View Source

The mounted widget tree of a running application.

One of these is built from the element tree render/1 returns and is what routes events, resolves selectors and remembers where each widget was drawn. Drafter.Test.get_widget_hierarchy/1 hands the whole struct to a test; the functions here are otherwise called by the framework rather than by an application.

The fields a test reads most:

  • :widgets - every mounted widget by id, each carrying its :module, :state, :parent, :children and :pid
  • :widget_rects - the rect a widget was last drawn into, by id, as %{x:, y:, width:, height:} in zero-based screen cells
  • :focused_widget - the id holding keyboard focus, or nil
  • :hover_widget - the id under the pointer, or nil
  • :root - the id of the outermost widget

Summary

Functions

Clear the per-dispatch consumption flag before routing a new event.

Snapshot the calling process's session context, as Drafter.Session.Context.capture/0.

The freshest state for a widget info map.

Record that a widget handled the event currently being routed.

Store widget_info under widget_id, replacing whatever was there.

Record how a widget should mark content that does not fit its width.

Stop every widget server the hierarchy holds.

Push new props into a widget.

Replace a widget's info map with fun.(info).

Reparent a widget. A widget the hierarchy does not hold is left alone.

Record a widget's rect and re-render it.

How a widget marks content that does not fit, defaulting to clipping.

Types

rect()

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

scroll_info()

@type scroll_info() :: %{
  viewport_rect: rect(),
  content_height: integer(),
  content_width: integer(),
  click_to_scroll: boolean(),
  scroll_exceptions: MapSet.t()
}

t()

@type t() :: %Drafter.WidgetHierarchy{
  drag_capture_widget: term(),
  event_consumed: term(),
  focused_widget: widget_id() | nil,
  hidden_widgets: term(),
  hover_widget: widget_id() | nil,
  preferred_sizes: term(),
  root: widget_id() | nil,
  scroll_containers: %{required(widget_id()) => scroll_info()},
  widget_counter: integer(),
  widget_overflow: term(),
  widget_rects: %{required(widget_id()) => rect()},
  widget_scroll_parents: %{required(widget_id()) => widget_id()},
  widgets: %{
    required(widget_id()) => %{
      module: module(),
      state: map(),
      parent: widget_id() | nil,
      children: [widget_id()],
      pid: pid() | nil,
      order: integer()
    }
  }
}

widget_id()

@type widget_id() :: atom() | String.t()

Functions

add_widget(hierarchy, widget_id, widget_module, mount_props, parent_id \\ nil, rect \\ %{x: 0, y: 0, width: 0, height: 0}, server_opts \\ [])

@spec add_widget(
  t(),
  widget_id(),
  module(),
  map(),
  widget_id() | nil,
  rect(),
  keyword()
) :: t()

clear_consumed(hierarchy)

@spec clear_consumed(t()) :: t()

Clear the per-dispatch consumption flag before routing a new event.

collect_session_pdict()

@spec collect_session_pdict() :: %{required(atom()) => pid()}

Snapshot the calling process's session context, as Drafter.Session.Context.capture/0.

get_children(hierarchy, parent_id)

@spec get_children(t(), widget_id()) :: [widget_id()]

get_parent(hierarchy, widget_id)

@spec get_parent(t(), widget_id()) :: widget_id() | nil

get_preferred_size(hierarchy, widget_id)

@spec get_preferred_size(t(), widget_id()) :: integer() | nil

get_widget_info(hierarchy, widget_id)

@spec get_widget_info(t(), widget_id()) :: map() | nil

get_widget_state(hierarchy, widget_id)

@spec get_widget_state(t(), widget_id()) :: map() | nil

live_widget_state(map)

@spec live_widget_state(map()) :: term()

The freshest state for a widget info map.

Asks the widget's server when it has one, falling back to the cached state if the server cannot answer. Returns the cached state directly for an inline widget.

mark_consumed(hierarchy)

@spec mark_consumed(t()) :: t()

Record that a widget handled the event currently being routed.

Consumption comes from the handler's own verdict, not from whether its state changed. Cleared before each dispatch by clear_consumed/1.

new(opts \\ [])

@spec new(keyword()) :: t()

put_widget(hierarchy, widget_id, widget_info)

@spec put_widget(t(), widget_id(), map()) :: t()

Store widget_info under widget_id, replacing whatever was there.

remove_widget(hierarchy, widget_id)

@spec remove_widget(t(), widget_id()) :: t()

set_widget_overflow(hierarchy, widget_id, mode)

@spec set_widget_overflow(t(), widget_id(), :clip | :ellipsis) :: t()

Record how a widget should mark content that does not fit its width.

:clip is the default and is not stored. Read back with widget_overflow/2.

set_widget_state(hierarchy, widget_id, new_state)

@spec set_widget_state(t(), widget_id(), map()) :: t()

stop_all_servers(hierarchy)

@spec stop_all_servers(t() | nil) :: :ok

Stop every widget server the hierarchy holds.

Widgets held inline and servers that have already exited are skipped, and a server that exits while being stopped is ignored. Always returns :ok, including for a nil hierarchy.

update_preferred_size(hierarchy, widget_id, size)

@spec update_preferred_size(t(), widget_id(), integer()) :: t()

update_widget(hierarchy, widget_id, new_props)

@spec update_widget(t(), widget_id(), map()) :: t()

Push new props into a widget.

A widget backed by a live server has them sent to it and the hierarchy comes back unchanged; a widget held inline has them merged into its cached state. A widget the hierarchy does not hold is ignored.

update_widget_info(hierarchy, widget_id, fun)

@spec update_widget_info(t(), widget_id(), (map() -> map())) :: t()

Replace a widget's info map with fun.(info).

A widget the hierarchy does not hold is left alone and fun is not called.

update_widget_parent(hierarchy, widget_id, parent_id)

@spec update_widget_parent(t(), widget_id(), widget_id() | nil) :: t()

Reparent a widget. A widget the hierarchy does not hold is left alone.

update_widget_rect(hierarchy, widget_id, rect)

@spec update_widget_rect(t(), widget_id(), rect()) :: t()

Record a widget's rect and re-render it.

The widget is re-rendered on every call, including when the rect is unchanged, so its strips reflect any state that moved since the last pass.

update_widget_state(hierarchy, widget_id, new_state)

@spec update_widget_state(t(), widget_id(), map()) :: t()

update_widget_state_in_hierarchy(hierarchy, widget_id, new_state)

@spec update_widget_state_in_hierarchy(t(), widget_id(), term()) :: t()

Replace a widget's whole state.

A widget backed by a live server has the state set on it and the hierarchy comes back unchanged; a widget held inline has its cached state replaced. A widget the hierarchy does not hold is ignored.

widget_overflow(hierarchy, widget_id)

@spec widget_overflow(t(), widget_id()) :: :clip | :ellipsis

How a widget marks content that does not fit, defaulting to clipping.