-module(etui@widgets@block). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/etui/widgets/block.gleam"). -export([block_new/0, with_bg_fill/1, with_border/2, with_title/3, with_title_styled/3, with_padding/5, with_title_alignment/2, with_style/3, with_colors/3, render/3, inner/2]). -export_type([border/0, title_position/0, block/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 border() :: none | single | double | rounded. -type title_position() :: top | bottom. -type block() :: {block, border(), binary(), list(etui@span:span()), title_position(), etui@text:alignment(), integer(), integer(), integer(), integer(), etui@style:color(), etui@style:color(), boolean()}. -file("src/etui/widgets/block.gleam", 49). ?DOC(" New block with no border, no title, no padding, default colors.\n"). -spec block_new() -> block(). block_new() -> {block, none, <<""/utf8>>, [], top, left, 0, 0, 0, 0, default, default, false}. -file("src/etui/widgets/block.gleam", 67). ?DOC(" Fill the inner area with the block's background color.\n"). -spec with_bg_fill(block()) -> block(). with_bg_fill(Blk) -> {block, erlang:element(2, Blk), erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), erlang:element(11, Blk), erlang:element(12, Blk), true}. -file("src/etui/widgets/block.gleam", 72). ?DOC(" Set the border style. `Single` draws ┌─┐│└─┘, `Double` ╔═╗║╚═╝, `Rounded` ╭─╮│╰─╯.\n"). -spec with_border(block(), border()) -> block(). with_border(Blk, Border) -> {block, Border, erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 77). ?DOC(" Set a title string and whether it appears on the top or bottom border.\n"). -spec with_title(block(), binary(), title_position()) -> block(). with_title(Blk, Title, Position) -> {block, erlang:element(2, Blk), Title, [], Position, erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 92). ?DOC( " Set a styled title from a list of `span.Span` values.\n" " Takes precedence over `with_title` when non-empty.\n" "\n" " ```gleam\n" " block.block_new()\n" " |> block.with_border(block.Rounded)\n" " |> block.with_title_styled([\n" " span.span_styled(\"★ \", style.bold_style() |> style.with_fg(style.Rgb(255,215,0))),\n" " span.span_plain(\"Dashboard\"),\n" " ], block.Top)\n" " ```\n" ). -spec with_title_styled(block(), list(etui@span:span()), title_position()) -> block(). with_title_styled(Blk, Spans, Position) -> {block, erlang:element(2, Blk), <<""/utf8>>, Spans, Position, erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 101). ?DOC(" Set inner padding (cells between border and content).\n"). -spec with_padding(block(), integer(), integer(), integer(), integer()) -> block(). with_padding(Blk, Top, Bottom, Left, Right) -> {block, erlang:element(2, Blk), erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), erlang:element(6, Blk), Top, Bottom, Left, Right, erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 118). ?DOC(" Set the horizontal alignment of the title within the border.\n"). -spec with_title_alignment(block(), etui@text:alignment()) -> block(). with_title_alignment(Blk, Alignment) -> {block, erlang:element(2, Blk), erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), Alignment, erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 123). ?DOC(" Set foreground and background colors for the border and title.\n"). -spec with_style(block(), etui@style:color(), etui@style:color()) -> block(). with_style(Blk, Fg, Bg) -> {block, erlang:element(2, Blk), erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), Fg, Bg, erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 128). ?DOC(" Alias for `with_style(fg, bg)`, consistent with other widget naming.\n"). -spec with_colors(block(), etui@style:color(), etui@style:color()) -> block(). with_colors(Blk, Fg, Bg) -> {block, erlang:element(2, Blk), erlang:element(3, Blk), erlang:element(4, Blk), erlang:element(5, Blk), erlang:element(6, Blk), erlang:element(7, Blk), erlang:element(8, Blk), erlang:element(9, Blk), erlang:element(10, Blk), Fg, Bg, erlang:element(13, Blk)}. -file("src/etui/widgets/block.gleam", 348). -spec inner_area(etui@geometry:rect(), block()) -> etui@geometry:rect(). inner_area(Area, Blk) -> Border_offset = case erlang:element(2, Blk) of none -> 0; single -> 1; double -> 1; rounded -> 1 end, X = (erlang:element(2, erlang:element(2, Area)) + erlang:element(9, Blk)) + Border_offset, Y = (erlang:element(3, erlang:element(2, Area)) + erlang:element(7, Blk)) + Border_offset, W = gleam@int:max( 0, ((erlang:element(2, erlang:element(3, Area)) - erlang:element(9, Blk)) - erlang:element( 10, Blk )) - (Border_offset * 2) ), H = gleam@int:max( 0, ((erlang:element(3, erlang:element(3, Area)) - erlang:element(7, Blk)) - erlang:element( 8, Blk )) - (Border_offset * 2) ), {rect, {position, X, Y}, {size, W, H}}. -file("src/etui/widgets/block.gleam", 310). -spec fill_bg_area( etui@buffer:buffer(), etui@geometry:rect(), etui@style:color(), etui@style:color(), integer() ) -> etui@buffer:buffer(). fill_bg_area(Buf, Area, Fg, Bg, Y) -> case Y >= (erlang:element(3, erlang:element(2, Area)) + erlang:element( 3, erlang:element(3, Area) )) of true -> Buf; false -> Row = etui@text:pad_right( <<""/utf8>>, erlang:element(2, erlang:element(3, Area)) ), Buf2 = etui@buffer:set_string( Buf, {position, erlang:element(2, erlang:element(2, Area)), Y}, Row, Fg, Bg, etui@style:none() ), fill_bg_area(Buf2, Area, Fg, Bg, Y + 1) end. -file("src/etui/widgets/block.gleam", 299). -spec render_content(etui@buffer:buffer(), etui@geometry:rect(), block()) -> etui@buffer:buffer(). render_content(Buf, Area, Blk) -> case erlang:element(13, Blk) of false -> etui@buffer:clear(Buf, Area); true -> fill_bg_area( Buf, Area, erlang:element(11, Blk), erlang:element(12, Blk), erlang:element(3, erlang:element(2, Area)) ) end. -file("src/etui/widgets/block.gleam", 251). -spec render_title(etui@buffer:buffer(), etui@geometry:rect(), block()) -> etui@buffer:buffer(). render_title(Buf, Area, Blk) -> X0 = erlang:element(2, erlang:element(2, Area)) + 1, Max_width = erlang:element(2, erlang:element(3, Area)) - 2, case erlang:element(4, Blk) of [_ | _] -> Y = case erlang:element(5, Blk) of top -> erlang:element(3, erlang:element(2, Area)); bottom -> etui@geometry:bottom(Area) - 1 end, Line = etui@span:line_aligned( erlang:element(4, Blk), erlang:element(6, Blk) ), etui@span:render_line(Buf, {position, X0, Y}, Line, Max_width); [] -> case erlang:element(3, Blk) of <<""/utf8>> -> Buf; Title -> Title_width = etui@text:cell_width(Title), T = case Title_width > Max_width of true -> etui@text:truncate(Title, Max_width, <<"…"/utf8>>); false -> Title end, T_width = etui@text:cell_width(T), X_offset = case erlang:element(6, Blk) of left -> 0; right -> gleam@int:max(0, Max_width - T_width); center -> gleam@int:max(0, (Max_width - T_width) div 2) end, Y@1 = case erlang:element(5, Blk) of top -> erlang:element(3, erlang:element(2, Area)); bottom -> etui@geometry:bottom(Area) - 1 end, etui@buffer:set_string( Buf, {position, X0 + X_offset, Y@1}, T, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none() ) end end. -file("src/etui/widgets/block.gleam", 397). -spec draw_vertical_line( etui@buffer:buffer(), integer(), integer(), integer(), etui@buffer:cell() ) -> etui@buffer:buffer(). draw_vertical_line(Buf, X, Y_start, Y_end, Cell) -> case Y_start > Y_end of true -> Buf; false -> Buf_new = etui@buffer:set_cell(Buf, {position, X, Y_start}, Cell), draw_vertical_line(Buf_new, X, Y_start + 1, Y_end, Cell) end. -file("src/etui/widgets/block.gleam", 380). -spec draw_horizontal_line( etui@buffer:buffer(), integer(), integer(), integer(), etui@buffer:cell() ) -> etui@buffer:buffer(). draw_horizontal_line(Buf, X_start, X_end, Y, Cell) -> case X_start > X_end of true -> Buf; false -> Buf_new = etui@buffer:set_cell(Buf, {position, X_start, Y}, Cell), draw_horizontal_line(Buf_new, X_start + 1, X_end, Y, Cell) end. -file("src/etui/widgets/block.gleam", 149). -spec render_bordered( etui@buffer:buffer(), etui@geometry:rect(), block(), binary(), binary(), binary(), binary(), binary(), binary() ) -> etui@buffer:buffer(). render_bordered( Buf, Area, Blk, Border_h, Border_v, Corner_tl, Corner_tr, Corner_bl, Corner_br ) -> Width = erlang:element(2, erlang:element(3, Area)), Height = erlang:element(3, erlang:element(3, Area)), case (Width < 2) orelse (Height < 2) of true -> Buf; false -> X0 = erlang:element(2, erlang:element(2, Area)), Y0 = erlang:element(3, erlang:element(2, Area)), Y_bottom = etui@geometry:bottom(Area) - 1, X_right = etui@geometry:right(Area) - 1, Cell_border = {cell, {content, Border_h, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>}, Buf1 = etui@buffer:set_cell( Buf, {position, X0, Y0}, {cell, {content, Corner_tl, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>} ), Buf2 = etui@buffer:set_cell( Buf1, {position, X_right, Y0}, {cell, {content, Corner_tr, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>} ), Buf3 = etui@buffer:set_cell( Buf2, {position, X0, Y_bottom}, {cell, {content, Corner_bl, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>} ), Buf4 = etui@buffer:set_cell( Buf3, {position, X_right, Y_bottom}, {cell, {content, Corner_br, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>} ), Buf5 = draw_horizontal_line( Buf4, X0 + 1, X_right - 1, Y0, Cell_border ), Buf6 = draw_horizontal_line( Buf5, X0 + 1, X_right - 1, Y_bottom, Cell_border ), Cell_v = {cell, {content, Border_v, 1}, erlang:element(11, Blk), erlang:element(12, Blk), etui@style:none(), <<""/utf8>>}, Buf7 = draw_vertical_line(Buf6, X0, Y0 + 1, Y_bottom - 1, Cell_v), Buf8 = draw_vertical_line( Buf7, X_right, Y0 + 1, Y_bottom - 1, Cell_v ), Buf9 = render_title(Buf8, Area, Blk), render_content(Buf9, inner_area(Area, Blk), Blk) end. -file("src/etui/widgets/block.gleam", 136). ?DOC(" Render block into buffer at given area.\n"). -spec render(etui@buffer:buffer(), etui@geometry:rect(), block()) -> etui@buffer:buffer(). render(Buf, Area, Blk) -> case erlang:element(2, Blk) of none -> render_content(Buf, Area, Blk); single -> render_bordered( Buf, Area, Blk, <<"─"/utf8>>, <<"│"/utf8>>, <<"┌"/utf8>>, <<"┐"/utf8>>, <<"└"/utf8>>, <<"┘"/utf8>> ); double -> render_bordered( Buf, Area, Blk, <<"═"/utf8>>, <<"║"/utf8>>, <<"╔"/utf8>>, <<"╗"/utf8>>, <<"╚"/utf8>>, <<"╝"/utf8>> ); rounded -> render_bordered( Buf, Area, Blk, <<"─"/utf8>>, <<"│"/utf8>>, <<"╭"/utf8>>, <<"╮"/utf8>>, <<"╰"/utf8>>, <<"╯"/utf8>> ) end. -file("src/etui/widgets/block.gleam", 344). ?DOC( " Inner area (content region) of a block, accounting for border and padding.\n" "\n" " Use this to get the Rect to pass to child widgets:\n" "\n" " ```gleam\n" " let b = block.block_new() |> block.with_border(block.Single)\n" " block.render(buf, area, b)\n" " |> paragraph.render(block.inner(area, b), p)\n" " ```\n" ). -spec inner(etui@geometry:rect(), block()) -> etui@geometry:rect(). inner(Area, Blk) -> inner_area(Area, Blk).