10 static void free_list(struct tui_widget *w, void *cls);
11 static void draw_list(struct tui_widget *w, void *cls);
13 struct tui_widget *tui_list(const char *title, int x, int y, int width, int height, tui_callback cbfunc, void *cbdata)
17 if(!(w = calloc(1, sizeof *w))) {
21 w->title = strdup(title);
27 w->entries = darr_alloc(0, sizeof *w->entries);
32 tui_set_callback((struct tui_widget*)w, TUI_ONMODIFY, cbfunc, cbdata);
34 tui_set_callback((struct tui_widget*)w, TUI_FREE, free_list, 0);
35 tui_set_callback((struct tui_widget*)w, TUI_DRAW, draw_list, 0);
36 return (struct tui_widget*)w;
39 static void free_list(struct tui_widget *w, void *cls)
41 struct tui_list *wl = (struct tui_list*)w;
44 darr_free(wl->entries);
48 void tui_clear_list(struct tui_widget *w)
51 struct tui_list *wl = (struct tui_list*)w;
52 assert(wl->type == TUI_LIST);
54 for(i=0; i<darr_size(wl->entries); i++) {
57 darr_clear(wl->entries);
60 tui_call_callback(w, TUI_ONMODIFY);
63 void tui_add_list_item(struct tui_widget *w, const char *text)
66 struct tui_list *wl = (struct tui_list*)w;
67 assert(wl->type == TUI_LIST);
68 str = strdup_nf(text);
69 darr_push(wl->entries, &str);
72 tui_call_callback(w, TUI_ONMODIFY);
75 int tui_num_list_items(struct tui_widget *w)
77 struct tui_list *wl = (struct tui_list*)w;
78 assert(wl->type == TUI_LIST);
79 return darr_size(wl->entries);
82 #define VISLINES(wl) ((wl)->height - 2)
84 int tui_list_select(struct tui_widget *w, int idx)
86 int offs, nelem, numvis;
87 struct tui_list *wl = (struct tui_list*)w;
88 assert(wl->type == TUI_LIST);
91 return 0; /* no change */
94 numvis = VISLINES(wl);
100 if(idx >= (nelem = darr_size(wl->entries))) {
105 if(idx < wl->view_offs || idx >= wl->view_offs + numvis) {
106 offs = idx - numvis / 2;
107 if(offs + numvis >= nelem) {
108 offs = nelem - numvis;
113 wl->view_offs = offs;
117 tui_call_callback(w, TUI_ONMODIFY);
121 int tui_get_list_sel(struct tui_widget *w)
123 struct tui_list *wl = (struct tui_list*)w;
124 assert(wl->type == TUI_LIST);
128 int tui_list_sel_next(struct tui_widget *w)
131 struct tui_list *wl = (struct tui_list*)w;
132 assert(wl->type == TUI_LIST);
134 nelem = darr_size(wl->entries);
136 numvis = VISLINES(wl);
138 if(wl->sel + 1 >= nelem) {
142 if(++wl->sel - wl->view_offs >= numvis) {
143 wl->view_offs = wl->sel - numvis + 1;
146 tui_call_callback(w, TUI_ONMODIFY);
150 int tui_list_sel_prev(struct tui_widget *w)
152 struct tui_list *wl = (struct tui_list*)w;
153 assert(wl->type == TUI_LIST);
158 if(--wl->sel < wl->view_offs) {
159 wl->view_offs = wl->sel;
162 tui_call_callback(w, TUI_ONMODIFY);
166 int tui_list_sel_start(struct tui_widget *w)
168 struct tui_list *wl = (struct tui_list*)w;
169 assert(wl->type == TUI_LIST);
174 tui_call_callback(w, TUI_ONMODIFY);
178 int tui_list_sel_end(struct tui_widget *w)
181 struct tui_list *wl = (struct tui_list*)w;
182 assert(wl->type == TUI_LIST);
184 nelem = darr_size(wl->entries);
185 numvis = VISLINES(wl);
188 wl->view_offs = nelem - numvis;
189 if(wl->view_offs < 0) wl->view_offs = 0;
191 tui_call_callback(w, TUI_ONMODIFY);
195 void tui_sort_list(struct tui_widget *w, int (*cmpfunc)(const void*, const void*))
198 struct tui_list *wl = (struct tui_list*)w;
199 assert(wl->type == TUI_LIST);
202 cmpfunc = (int (*)(const void*, const void*))strcmp;
205 nelem = darr_size(wl->entries);
206 qsort(wl->entries, nelem, sizeof *wl->entries, cmpfunc);
209 tui_call_callback(w, TUI_ONMODIFY);
212 static void draw_list(struct tui_widget *w, void *cls)
214 int i, x, y, num, idx;
215 struct tui_list *wl = (struct tui_list*)w;
217 tui_wtoscr(w, 0, 0, &x, &y);
219 tg_bgcolor(TGFX_BLUE);
220 tg_fgcolor(TGFX_CYAN);
221 tg_rect(wl->title, x, y, wl->width, wl->height, TGFX_FRAME);
223 num = darr_size(wl->entries);
224 if(num > wl->height - 2) {
225 num = wl->height - 2;
229 for(i=0; i<num; i++) {
230 idx = i + wl->view_offs;
231 if(w->focus && idx == wl->sel) {
232 tg_bgcolor(TGFX_CYAN);
233 tg_fgcolor(TGFX_BLUE);
235 tg_rect(0, x, ++y, wl->width-2, 1, 0);
236 tg_text(x, y, "%s", wl->entries[idx]);
238 tg_bgcolor(TGFX_BLUE);
239 tg_fgcolor(TGFX_CYAN);
241 tg_text(x, ++y, "%s", wl->entries[idx]);