Skip to main content

src/etui@widget.erl

-module(etui@widget).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/etui/widget.gleam").
-export([render_stateful/4, freeze/2, freeze_frame/2, layer/2, at/2, compose/3, stack/1, empty/0]).
-export_type([stateful_widget/1]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

-type stateful_widget(FER) :: {stateful_widget,
        fun((etui@buffer:buffer(), etui@geometry:rect(), FER) -> etui@buffer:buffer())}.

-file("src/etui/widget.gleam", 102).
?DOC(" Render a stateful widget with the given state value.\n").
-spec render_stateful(
    etui@buffer:buffer(),
    etui@geometry:rect(),
    stateful_widget(FES),
    FES
) -> etui@buffer:buffer().
render_stateful(Buf, Area, W, State) ->
    (erlang:element(2, W))(Buf, Area, State).

-file("src/etui/widget.gleam", 113).
?DOC(
    " Bake state into a stateless Widget.\n"
    " The resulting Widget ignores any state updates after this call.\n"
).
-spec freeze(stateful_widget(FEU), FEU) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
freeze(W, State) ->
    fun(Buf, Area) -> (erlang:element(2, W))(Buf, Area, State) end.

-file("src/etui/widget.gleam", 121).
?DOC(" Bind a frame number to an AnimatedWidget, producing a stateless Widget.\n").
-spec freeze_frame(
    fun((etui@buffer:buffer(), etui@geometry:rect(), integer()) -> etui@buffer:buffer()),
    integer()
) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
freeze_frame(W, Frame) ->
    fun(Buf, Area) -> W(Buf, Area, Frame) end.

-file("src/etui/widget.gleam", 130).
?DOC(
    " Draw two widgets in the same area: `bottom` first, then `top` on top.\n"
    " Use for overlaying a popup, cursor, or status indicator over content.\n"
).
-spec layer(
    fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()),
    fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer())
) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
layer(Bottom, Top) ->
    fun(Buf, Area) -> _pipe = Buf,
        _pipe@1 = Bottom(_pipe, Area),
        Top(_pipe@1, Area) end.

-file("src/etui/widget.gleam", 136).
?DOC(
    " Pin a widget to a fixed `sub_area`, ignoring the caller-supplied area.\n"
    " Use when a widget's position is pre-computed and shouldn't be overridden.\n"
).
-spec at(
    fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()),
    etui@geometry:rect()
) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
at(W, Sub_area) ->
    fun(Buf, _) -> W(Buf, Sub_area) end.

-file("src/etui/widget.gleam", 153).
?DOC(
    " Render `border_w` over `area`, then `content_w` over `inner_area`.\n"
    " Convenience for the common \"block border + child content\" pattern:\n"
    "\n"
    " ```gleam\n"
    " let blk = block.block_new() |> block.with_border(block.Single)\n"
    " let inner = block.inner(area, blk)\n"
    " let composed = widget.compose(\n"
    "   fn(buf, a) { block.render(buf, a, blk) },\n"
    "   inner,\n"
    "   fn(buf, a) { paragraph.render(buf, a, para) },\n"
    " )\n"
    " composed(buf, area)\n"
    " ```\n"
).
-spec compose(
    fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()),
    etui@geometry:rect(),
    fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer())
) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
compose(Border_w, Inner_area, Content_w) ->
    fun(Buf, Area) -> _pipe = Buf,
        _pipe@1 = Border_w(_pipe, Area),
        Content_w(_pipe@1, Inner_area) end.

-file("src/etui/widget.gleam", 166).
-spec fold_widgets(
    etui@buffer:buffer(),
    etui@geometry:rect(),
    list(fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()))
) -> etui@buffer:buffer().
fold_widgets(Buf, Area, Widgets) ->
    case Widgets of
        [] ->
            Buf;

        [W | Rest] ->
            fold_widgets(W(Buf, Area), Area, Rest)
    end.

-file("src/etui/widget.gleam", 162).
?DOC(" Apply a list of widgets to the same area in order (each draws on top of the previous).\n").
-spec stack(
    list(fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()))
) -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
stack(Widgets) ->
    fun(Buf, Area) -> fold_widgets(Buf, Area, Widgets) end.

-file("src/etui/widget.gleam", 181).
?DOC(" A widget that renders nothing. Useful as a default or placeholder.\n").
-spec empty() -> fun((etui@buffer:buffer(), etui@geometry:rect()) -> etui@buffer:buffer()).
empty() ->
    fun(Buf, _) -> Buf end.