Ajla 0.1.0
[ajla.git] / newlib / ui / widget / text.ajla
blobb3cea84d217d17eecf330008c6ba0c96b7c6481e
1 {*
2  * Copyright (C) 2024 Mikulas Patocka
3  *
4  * This file is part of Ajla.
5  *
6  * Ajla is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Ajla. If not, see <https://www.gnu.org/licenses/>.
17  *}
19 private unit ui.widget.text;
21 uses ui.widget.common;
23 type text_state;
25 fn text_init(align : widget_align, label : string, color_scheme : bytes, w : world, app : appstate, id : wid) : (world, appstate, text_state);
26 fn text_get_width(app : appstate, com : widget_common, st : text_state, x : int) : int;
27 fn text_get_height(app : appstate, com : widget_common, st : text_state, x : int) : int;
28 fn text_reflow(app : appstate, com : widget_common, st : text_state) : (appstate, widget_common, text_state);
29 fn text_redraw(app : appstate, curs : curses, com : widget_common, st : text_state) : curses;
31 const text_class~flat := widget_class.[
32         t : text_state,
33         name : "text",
34         is_selectable : false,
35         get_width : text_get_width,
36         get_height : text_get_height,
37         reflow : text_reflow,
38         redraw : text_redraw,
41 implementation
43 record text_state [
44         align : widget_align;
45         label : string;
46         color_scheme : bytes;
47         flow : list(string);
50 fn text_init(align : widget_align, label : string, color_scheme : bytes, implicit w : world, implicit app : appstate, id : wid) : (world, appstate, text_state)
52         return text_state.[
53                 align : align,
54                 label : label,
55                 color_scheme : color_scheme,
56                 flow : [ label ],
57         ];
60 fn reflow(label : string, x : int, hard_break : bool) : list(string)
62         var lbr := -1;
63         var tmp_line := empty(char);
64         var tmp_len := 0;
65         var result := empty(string);
66         for i := 0 to len(label) do [
67                 var c := label[i];
68                 if c = u_nl then [
69                         result +<= tmp_line;
70                         tmp_line := empty(char);
71                         tmp_len := 0;
72                         lbr := -1;
73                         continue;
74                 ]
75                 if c = ' ' then
76                         lbr := len(tmp_line);
77                 tmp_line +<= c;
78                 tmp_len += char_length(c);
79                 if tmp_len > x then [
80                         if lbr >= 0 then [
81                                 result +<= tmp_line[ .. lbr];
82                                 tmp_line := tmp_line[lbr + 1 .. ];
83                         ] else if hard_break, tmp_len > 1 then [
84                                 result +<= tmp_line[ .. tmp_len - 1];
85                                 tmp_line := tmp_line[tmp_len - 1 .. ];
86                         ]
87                         tmp_len := string_length(tmp_line);
88                         lbr := -1;
89                 ]
90         ]
91         if tmp_len > 0 then
92                 result +<= tmp_line;
93         return result;
96 fn text_get_width(app : appstate, com : widget_common, st : text_state, x : int) : int
98         var flow := reflow(st.label, x, false);
99         var x := 0;
100         for i := 0 to len(flow) do
101                 x := max(x, len(flow[i]));
102         return x;
105 fn text_get_height(app : appstate, com : widget_common, st : text_state, x : int) : int
107         var flow := reflow(st.label, x, true);
108         return len(flow);
111 fn text_reflow(implicit app : appstate, implicit com : widget_common, implicit st : text_state) : (appstate, widget_common, text_state)
113         var flow := reflow(st.label, com.size_x, true);
114         st.flow := flow;
117 fn text_redraw(implicit app : appstate, implicit curs : curses, com : widget_common, st : text_state) : curses
119         property_set_attrib(property_get_attrib(st.color_scheme + "text", #0000, #0000, #0000, #aaaa, #aaaa, #aaaa, 0, curses_invert));
120         curses_fill_rect(0, com.size_x, 0, com.size_y, ' ');
121         for i := 0 to len(st.flow) do [
122                 var s := st.flow[i];
123                 var x := 0;
124                 if st.align is center then
125                         x := com.size_x - string_length(s) shr 1;
126                 else if st.align is right then
127                         x := com.size_x - string_length(s);
128                 curses_set_pos(x, i);
129                 curses_print(s);
130         ]