-module(etui@widgets@chart). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/etui/widgets/chart.gleam"). -export([chart_new/1, with_fill/2, with_max/2, with_bar_width/2, with_gap/2, with_period/2, with_bg/2, with_style/2, render/4]). -export_type([chart_fill/0, chart/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 chart_fill() :: {chart_solid, list(etui@style:color())} | {chart_gradient, list(etui@style:color())} | chart_rainbow | chart_animated_rainbow | {chart_vertical_gradient, list(etui@style:color())}. -type chart() :: {chart, list(integer()), integer(), chart_fill(), integer(), integer(), binary(), etui@style:color(), integer()}. -file("src/etui/widgets/chart.gleam", 48). -spec chart_new(list(integer())) -> chart(). chart_new(Data) -> {chart, Data, 0, chart_rainbow, 2, 1, <<"█"/utf8>>, default, 60}. -file("src/etui/widgets/chart.gleam", 61). -spec with_fill(chart(), chart_fill()) -> chart(). with_fill(C, Fill) -> {chart, erlang:element(2, C), erlang:element(3, C), Fill, erlang:element(5, C), erlang:element(6, C), erlang:element(7, C), erlang:element(8, C), erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 65). -spec with_max(chart(), integer()) -> chart(). with_max(C, Max) -> {chart, erlang:element(2, C), gleam@int:max(1, Max), erlang:element(4, C), erlang:element(5, C), erlang:element(6, C), erlang:element(7, C), erlang:element(8, C), erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 69). -spec with_bar_width(chart(), integer()) -> chart(). with_bar_width(C, W) -> {chart, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), gleam@int:max(1, W), erlang:element(6, C), erlang:element(7, C), erlang:element(8, C), erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 73). -spec with_gap(chart(), integer()) -> chart(). with_gap(C, G) -> {chart, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), erlang:element(5, C), gleam@int:max(0, G), erlang:element(7, C), erlang:element(8, C), erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 77). -spec with_period(chart(), integer()) -> chart(). with_period(C, Period) -> {chart, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), erlang:element(5, C), erlang:element(6, C), erlang:element(7, C), erlang:element(8, C), gleam@int:max(1, Period)}. -file("src/etui/widgets/chart.gleam", 81). -spec with_bg(chart(), etui@style:color()) -> chart(). with_bg(C, Bg) -> {chart, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), erlang:element(5, C), erlang:element(6, C), erlang:element(7, C), Bg, erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 85). -spec with_style(chart(), etui@style:style()) -> chart(). with_style(C, S) -> {chart, erlang:element(2, C), erlang:element(3, C), erlang:element(4, C), erlang:element(5, C), erlang:element(6, C), erlang:element(7, C), erlang:element(3, S), erlang:element(9, C)}. -file("src/etui/widgets/chart.gleam", 304). -spec get_color_at(list(etui@style:color()), integer()) -> etui@style:color(). get_color_at(Colors, N) -> case {Colors, N} of {[], _} -> default; {[C | _], 0} -> C; {[_ | Rest], _} -> get_color_at(Rest, N - 1) end. -file("src/etui/widgets/chart.gleam", 296). -spec get_nth_color(list(etui@style:color()), integer()) -> etui@style:color(). get_nth_color(Colors, N) -> Len = erlang:length(Colors), case Len of 0 -> default; _ -> get_color_at(Colors, case Len of 0 -> 0; Gleam@denominator -> N rem Gleam@denominator end) end. -file("src/etui/widgets/chart.gleam", 273). -spec bar_color( chart_fill(), integer(), integer(), integer(), integer(), integer(), integer() ) -> etui@style:color(). bar_color(Fill, Bar_idx, N_bars, Dy, Height, Frame, Period) -> P = gleam@int:max(1, Period), N = gleam@int:max(1, N_bars), H = gleam@int:max(1, Height), case Fill of {chart_solid, Colors} -> get_nth_color(Colors, Bar_idx); {chart_gradient, Stops} -> etui@color:gradient(Stops, Bar_idx, N - 1); chart_rainbow -> etui@color:hue_to_rgb(case N of 0 -> 0; Gleam@denominator -> Bar_idx * 360 div Gleam@denominator end); chart_animated_rainbow -> etui@color:hue_to_rgb(((case N of 0 -> 0; Gleam@denominator@1 -> Bar_idx * 360 div Gleam@denominator@1 end) + (case P of 0 -> 0; Gleam@denominator@2 -> Frame * 360 div Gleam@denominator@2 end)) rem 360); {chart_vertical_gradient, Stops@1} -> etui@color:gradient(Stops@1, (Height - 1) - Dy, H - 1) end. -file("src/etui/widgets/chart.gleam", 226). -spec render_bar_rows( etui@buffer:buffer(), etui@geometry:rect(), chart(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) -> etui@buffer:buffer(). render_bar_rows( Buf, Area, C, Bar_idx, N_bars, X, Height, Filled_rows, Frame, Dy ) -> case Dy >= Height of true -> Buf; false -> Rows_from_bottom = (Height - 1) - Dy, Is_filled = Rows_from_bottom < Filled_rows, Pos = {position, erlang:element(2, erlang:element(2, Area)) + X, erlang:element(3, erlang:element(2, Area)) + Dy}, Buf2 = case Is_filled of true -> Fg = bar_color( erlang:element(4, C), Bar_idx, N_bars, Dy, Height, Frame, erlang:element(9, C) ), etui@buffer:set_string( Buf, Pos, erlang:element(7, C), Fg, erlang:element(8, C), etui@style:none() ); false -> Buf end, render_bar_rows( Buf2, Area, C, Bar_idx, N_bars, X, Height, Filled_rows, Frame, Dy + 1 ) end. -file("src/etui/widgets/chart.gleam", 176). -spec render_bar_cols_inner( etui@buffer:buffer(), etui@geometry:rect(), chart(), integer(), integer(), integer(), integer(), integer(), integer(), integer() ) -> etui@buffer:buffer(). render_bar_cols_inner( Buf, Area, C, Bar_idx, N_bars, Col_start, Height, Filled_rows, Frame, Dc ) -> case Dc >= erlang:element(5, C) of true -> Buf; false -> X = Col_start + Dc, case X >= erlang:element(2, erlang:element(3, Area)) of true -> Buf; false -> Buf2 = render_bar_rows( Buf, Area, C, Bar_idx, N_bars, X, Height, Filled_rows, Frame, 0 ), render_bar_cols_inner( Buf2, Area, C, Bar_idx, N_bars, Col_start, Height, Filled_rows, Frame, Dc + 1 ) end end. -file("src/etui/widgets/chart.gleam", 151). -spec render_bar_col( etui@buffer:buffer(), etui@geometry:rect(), chart(), integer(), integer(), integer(), integer(), integer(), integer() ) -> etui@buffer:buffer(). render_bar_col( Buf, Area, C, Bar_idx, N_bars, Col_start, Height, Filled_rows, Frame ) -> render_bar_cols_inner( Buf, Area, C, Bar_idx, N_bars, Col_start, Height, Filled_rows, Frame, 0 ). -file("src/etui/widgets/chart.gleam", 112). -spec render_bars( etui@buffer:buffer(), etui@geometry:rect(), chart(), list(integer()), integer(), integer(), integer(), integer() ) -> etui@buffer:buffer(). render_bars(Buf, Area, C, Data, Bar_idx, N_bars, Max, Frame) -> case Data of [] -> Buf; [Val | Rest] -> Col_start = Bar_idx * (erlang:element(5, C) + erlang:element(6, C)), case Col_start >= erlang:element(2, erlang:element(3, Area)) of true -> Buf; false -> H = erlang:element(3, erlang:element(3, Area)), Filled_rows = case gleam@int:max(1, Max) of 0 -> 0; Gleam@denominator -> Val * H div Gleam@denominator end, Buf2 = render_bar_col( Buf, Area, C, Bar_idx, N_bars, Col_start, H, Filled_rows, Frame ), render_bars( Buf2, Area, C, Rest, Bar_idx + 1, N_bars, Max, Frame ) end end. -file("src/etui/widgets/chart.gleam", 93). ?DOC(" Render chart into `area`. `frame` drives animated fills.\n"). -spec render(etui@buffer:buffer(), etui@geometry:rect(), chart(), integer()) -> etui@buffer:buffer(). render(Buf, Area, C, Frame) -> case (erlang:element(2, erlang:element(3, Area)) =< 0) orelse (erlang:element( 3, erlang:element(3, Area) ) =< 0) of true -> Buf; false -> Max = case erlang:element(3, C) of 0 -> gleam@list:fold( erlang:element(2, C), 1, fun gleam@int:max/2 ); M -> M end, N_bars = erlang:length(erlang:element(2, C)), render_bars( Buf, Area, C, erlang:element(2, C), 0, N_bars, Max, Frame ) end.