Skip to main content

src/etui@widgets@line_gauge.erl

-module(etui@widgets@line_gauge).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/etui/widgets/line_gauge.gleam").
-export([line_gauge_new/1, with_label/2, with_line_set/2, with_colors/3, with_style/2, with_filled_modifier/2, render/3]).
-export_type([line_set/0, line_gauge/0, line_chars/0]).

-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 line_set() :: thin_line |
    double_line |
    thick_line |
    braille_line |
    ascii_line.

-type line_gauge() :: {line_gauge,
        integer(),
        binary(),
        line_set(),
        etui@style:color(),
        etui@style:color(),
        etui@style:modifier(),
        etui@style:modifier()}.

-type line_chars() :: {line_chars, binary(), binary()}.

-file("src/etui/widgets/line_gauge.gleam", 60).
?DOC(" New line gauge at the given percent (clamped to 0–100).\n").
-spec line_gauge_new(integer()) -> line_gauge().
line_gauge_new(Percent) ->
    {line_gauge,
        gleam@int:clamp(Percent, 0, 100),
        <<""/utf8>>,
        thin_line,
        default,
        default,
        etui@style:none(),
        etui@style:dim()}.

-file("src/etui/widgets/line_gauge.gleam", 73).
?DOC(" Set a label shown in the center of the gauge.\n").
-spec with_label(line_gauge(), binary()) -> line_gauge().
with_label(G, Label) ->
    {line_gauge,
        erlang:element(2, G),
        Label,
        erlang:element(4, G),
        erlang:element(5, G),
        erlang:element(6, G),
        erlang:element(7, G),
        erlang:element(8, G)}.

-file("src/etui/widgets/line_gauge.gleam", 78).
?DOC(" Set the line character set.\n").
-spec with_line_set(line_gauge(), line_set()) -> line_gauge().
with_line_set(G, Ls) ->
    {line_gauge,
        erlang:element(2, G),
        erlang:element(3, G),
        Ls,
        erlang:element(5, G),
        erlang:element(6, G),
        erlang:element(7, G),
        erlang:element(8, G)}.

-file("src/etui/widgets/line_gauge.gleam", 83).
?DOC(" Set foreground and background colors.\n").
-spec with_colors(line_gauge(), etui@style:color(), etui@style:color()) -> line_gauge().
with_colors(G, Fg, Bg) ->
    {line_gauge,
        erlang:element(2, G),
        erlang:element(3, G),
        erlang:element(4, G),
        Fg,
        Bg,
        erlang:element(7, G),
        erlang:element(8, G)}.

-file("src/etui/widgets/line_gauge.gleam", 92).
?DOC(" Set fg/bg from a Style value.\n").
-spec with_style(line_gauge(), etui@style:style()) -> line_gauge().
with_style(G, S) ->
    {line_gauge,
        erlang:element(2, G),
        erlang:element(3, G),
        erlang:element(4, G),
        erlang:element(2, S),
        erlang:element(3, S),
        erlang:element(7, G),
        erlang:element(8, G)}.

-file("src/etui/widgets/line_gauge.gleam", 97).
?DOC(" Apply a modifier to the filled portion.\n").
-spec with_filled_modifier(line_gauge(), etui@style:modifier()) -> line_gauge().
with_filled_modifier(G, M) ->
    {line_gauge,
        erlang:element(2, G),
        erlang:element(3, G),
        erlang:element(4, G),
        erlang:element(5, G),
        erlang:element(6, G),
        M,
        erlang:element(8, G)}.

-file("src/etui/widgets/line_gauge.gleam", 108).
-spec line_chars(line_set()) -> line_chars().
line_chars(Ls) ->
    case Ls of
        thin_line ->
            {line_chars, <<"─"/utf8>>, <<"─"/utf8>>};

        double_line ->
            {line_chars, <<"═"/utf8>>, <<"═"/utf8>>};

        thick_line ->
            {line_chars, <<"━"/utf8>>, <<"─"/utf8>>};

        braille_line ->
            {line_chars, <<"⣿"/utf8>>, <<"⣀"/utf8>>};

        ascii_line ->
            {line_chars, <<"="/utf8>>, <<"-"/utf8>>}
    end.

-file("src/etui/widgets/line_gauge.gleam", 199).
-spec drop_cells(binary(), integer()) -> binary().
drop_cells(S, N) ->
    case N =< 0 of
        true ->
            S;

        false ->
            Prefix = etui@text:truncate(S, N, <<""/utf8>>),
            gleam@string:drop_start(S, string:length(Prefix))
    end.

-file("src/etui/widgets/line_gauge.gleam", 183).
-spec overlay_label(binary(), binary(), integer()) -> binary().
overlay_label(Base, Label, Width) ->
    Lw = etui@text:cell_width(Label),
    case Lw >= Width of
        true ->
            etui@text:truncate(Label, Width, <<""/utf8>>);

        false ->
            Left_pad = (Width - Lw) div 2,
            Right_pad = (Width - Lw) - Left_pad,
            Left_str = etui@text:truncate(Base, Left_pad, <<""/utf8>>),
            Right_str = etui@text:truncate(
                drop_cells(Base, Left_pad + Lw),
                Right_pad,
                <<""/utf8>>
            ),
            <<<<Left_str/binary, Label/binary>>/binary, Right_str/binary>>
    end.

-file("src/etui/widgets/line_gauge.gleam", 175).
-spec repeat_char_loop(binary(), integer(), binary()) -> binary().
repeat_char_loop(Ch, N, Acc) ->
    case N =< 0 of
        true ->
            Acc;

        false ->
            repeat_char_loop(Ch, N - 1, <<Acc/binary, Ch/binary>>)
    end.

-file("src/etui/widgets/line_gauge.gleam", 171).
-spec repeat_char(binary(), integer()) -> binary().
repeat_char(Ch, N) ->
    repeat_char_loop(Ch, N, <<""/utf8>>).

-file("src/etui/widgets/line_gauge.gleam", 122).
?DOC(" Render the line gauge into the first row of `area`.\n").
-spec render(etui@buffer:buffer(), etui@geometry:rect(), line_gauge()) -> etui@buffer:buffer().
render(Buf, Area, G) ->
    case erlang:element(2, erlang:element(3, Area)) =< 0 of
        true ->
            Buf;

        false ->
            Width = erlang:element(2, erlang:element(3, Area)),
            Filled_w = (Width * erlang:element(2, G)) div 100,
            Unfilled_w = Width - Filled_w,
            Chars = line_chars(erlang:element(4, G)),
            Filled_str = repeat_char(erlang:element(2, Chars), Filled_w),
            Unfilled_str = repeat_char(erlang:element(3, Chars), Unfilled_w),
            Raw_line = <<Filled_str/binary, Unfilled_str/binary>>,
            Line = case erlang:element(3, G) of
                <<""/utf8>> ->
                    Raw_line;

                _ ->
                    overlay_label(Raw_line, erlang:element(3, G), Width)
            end,
            Pos = erlang:element(2, Area),
            Y = erlang:element(3, Pos),
            Buf@1 = etui@buffer:set_string(
                Buf,
                {position, erlang:element(2, Pos), Y},
                etui@text:truncate(Line, Filled_w, <<""/utf8>>),
                erlang:element(5, G),
                erlang:element(6, G),
                erlang:element(7, G)
            ),
            etui@buffer:set_string(
                Buf@1,
                {position, erlang:element(2, Pos) + Filled_w, Y},
                etui@text:truncate(
                    drop_cells(Line, Filled_w),
                    Unfilled_w,
                    <<""/utf8>>
                ),
                erlang:element(5, G),
                erlang:element(6, G),
                erlang:element(8, G)
            )
    end.