screen (cellium v0.1.0)

View Source

Screen management module for handling UI screen lifecycle and transitions.

This module provides a higher-level abstraction over widgets and focus management, allowing applications to manage distinct screens (like search, customer form, etc.) with automatic cleanup and focus handling.

Screen Lifecycle

  1. Create: Build a screen's widget tree using DSL or direct construction
  2. Show: Display the screen and register focusable widgets
  3. Hide: Hide the screen and unregister widgets (without destroying)
  4. Destroy: Permanently remove the screen and clean up resources

Usage

Basic screen transition:

% Build the new screen
CustomerScreen = screen:new(customer_form, fun() ->
    cellium_dsl:from_dsl({vbox, [{id, customer_form}], [
        {text_input, [{id, name_field}, {focusable, true}]},
        {button, [{id, save_btn}, {focusable, true}], "Save"}
    ]})
end),

% Switch from search to customer screen
screen:transition(SearchScreen, CustomerScreen)

Using a screen stack:

% Push a new screen (like opening a dialog)
screen:push(DialogScreen),

% Pop back to previous screen
screen:pop()

Screen Structure

A screen is a map containing:

  • id: Unique screen identifier
  • widget_tree: The root widget (typically a container)
  • active: Whether the screen is currently shown
  • builder: Optional function to rebuild the screen

Summary

Functions

Returns the current active screen, if any.

Destroys a screen permanently, cleaning up all widgets.

Gets the widget tree from a screen.

Hides a screen, unregistering all its focusable widgets from the focus manager.

Creates a new screen with a widget tree.

Creates a new screen with a builder function.

Pops the current screen from the stack, returning to the previous screen.

Pushes a new screen onto the stack, hiding the current screen.

Replaces the current screen in the managed stack with a new screen.

Shows a screen, registering all its focusable widgets with the focus manager.

Returns the entire screen stack for debugging purposes.

Starts the screen manager gen_server.

Transitions from one screen to another.

Updates the widget tree of a screen.

Functions

code_change(OldVsn, State, Extra)

current()

-spec current() -> {ok, map()} | {error, no_screen}.

Returns the current active screen, if any.

Returns {ok, Screen} or {error, no_screen} if the stack is empty.

destroy(Screen)

-spec destroy(Screen :: map()) -> ok.

Destroys a screen permanently, cleaning up all widgets.

Use this when a screen will not be used again. For temporary hiding, use screen:hide/1 instead.

get_widget_tree(Screen)

-spec get_widget_tree(Screen :: map()) -> map().

Gets the widget tree from a screen.

Returns the root widget map of the screen's widget tree.

handle_call/3

handle_cast(Request, State)

handle_info(Info, State)

hide(Screen)

-spec hide(Screen :: map()) -> map().

Hides a screen, unregistering all its focusable widgets from the focus manager.

The widget tree is preserved so the screen can be shown again later. Returns the screen with active => false.

init/1

new(ScreenId, WidgetTree)

-spec new(ScreenId :: term(), WidgetTree :: map()) -> map().

Creates a new screen with a widget tree.

The widget tree should already be built but not yet "created" (widgets not registered). Call screen:show/1 to activate the screen and register its widgets.

Example

SearchScreen = screen:new(search_screen,
    cellium_dsl:from_dsl({vbox, [], [
        {text_input, [{id, search_box}, {focusable, true}]}
    ]}))

new(ScreenId, BuilderFun, InitialTree)

-spec new(ScreenId :: term(), BuilderFun :: fun(() -> map()), InitialTree :: map()) -> map().

Creates a new screen with a builder function.

The builder function will be called to create the widget tree when the screen is shown. This is useful for screens that need to rebuild with fresh data each time they're displayed.

Example

screen:new(customer_form,
    fun() -> build_customer_form(get_customer_data()) end,
    empty_widget())

pop()

-spec pop() -> {ok, ScreenId :: term()} | {error, no_previous_screen}.

Pops the current screen from the stack, returning to the previous screen.

The popped screen is destroyed. The previous screen is shown and becomes current. Returns {ok, PreviousScreenId} or {error, no_previous_screen} if there is only one screen in the stack.

push(NewScreen)

-spec push(NewScreen :: map()) -> ok | {error, term()}.

Pushes a new screen onto the stack, hiding the current screen.

The current screen remains in memory and can be returned to with screen:pop/0. This is useful for modal dialogs or nested navigation.

Example

screen:push(ConfirmDialog),  % Shows dialog, hides current screen
% User interacts with dialog...
screen:pop()                  % Returns to previous screen

replace(NewScreen)

-spec replace(NewScreen :: map()) -> ok | {error, term()}.

Replaces the current screen in the managed stack with a new screen.

If there is a current screen, it is hidden and the new screen is shown. The current screen is replaced in the stack (not pushed).

Requires the screen manager to be running.

show(Screen)

-spec show(Screen :: map()) -> map().

Shows a screen, registering all its focusable widgets with the focus manager.

If the screen has a builder function, it will be called to rebuild the widget tree. Returns the screen with active => true.

stack()

-spec stack() -> [map()].

Returns the entire screen stack for debugging purposes.

The list is ordered with the current screen first, followed by previously pushed screens.

start_link()

-spec start_link() -> {ok, Pid :: pid()} | {error, term()}.

Starts the screen manager gen_server.

The screen manager maintains a stack of screens and handles transitions between them. It is automatically started by the cellium supervisor.

terminate(Reason, State)

transition(OldScreen, NewScreen)

-spec transition(OldScreen :: map(), NewScreen :: map()) -> map().

Transitions from one screen to another.

Hides the old screen (unregistering its widgets) and shows the new screen (registering its widgets). This is the recommended way to switch between screens.

Returns the new screen with active => true.

Example

NewScreen = screen:transition(SearchScreen, CustomerFormScreen)

update_widget_tree(Screen, NewTree)

-spec update_widget_tree(Screen :: map(), NewTree :: map()) -> map().

Updates the widget tree of a screen.

If the screen is active, destroys the old tree and registers the new one. If the screen is inactive, just updates the tree without registration.

Returns the updated screen map.