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 int tui_list_select(struct tui_widget *w, int idx)
85 struct tui_list *wl = (struct tui_list*)w;
86 assert(wl->type == TUI_LIST);
89 return 0; /* no change */
96 if(idx >= (nelem = darr_size(wl->entries))) {
101 if(idx < wl->view_offs || idx >= wl->view_offs + wl->height) {
102 offs = idx - wl->height / 2;
103 if(offs + wl->height >= nelem) {
104 offs = nelem - wl->height;
109 wl->view_offs = offs;
113 tui_call_callback(w, TUI_ONMODIFY);
117 int tui_get_list_sel(struct tui_widget *w)
119 struct tui_list *wl = (struct tui_list*)w;
120 assert(wl->type == TUI_LIST);
124 int tui_list_sel_next(struct tui_widget *w)
127 struct tui_list *wl = (struct tui_list*)w;
128 assert(wl->type == TUI_LIST);
130 nelem = darr_size(wl->entries);
132 if(wl->sel + 1 >= nelem) {
136 if(++wl->sel - wl->view_offs >= wl->height) {
137 wl->view_offs = wl->sel - wl->height;
140 tui_call_callback(w, TUI_ONMODIFY);
144 int tui_list_sel_prev(struct tui_widget *w)
146 struct tui_list *wl = (struct tui_list*)w;
147 assert(wl->type == TUI_LIST);
152 if(--wl->sel < wl->view_offs) {
153 wl->view_offs = wl->sel;
156 tui_call_callback(w, TUI_ONMODIFY);
160 int tui_list_sel_start(struct tui_widget *w)
162 struct tui_list *wl = (struct tui_list*)w;
163 assert(wl->type == TUI_LIST);
168 tui_call_callback(w, TUI_ONMODIFY);
172 int tui_list_sel_end(struct tui_widget *w)
175 struct tui_list *wl = (struct tui_list*)w;
176 assert(wl->type == TUI_LIST);
178 nelem = darr_size(wl->entries);
181 wl->view_offs = nelem - wl->height;
182 if(wl->view_offs < 0) wl->view_offs = 0;
184 tui_call_callback(w, TUI_ONMODIFY);
188 void tui_sort_list(struct tui_widget *w, int (*cmpfunc)(const void*, const void*))
191 struct tui_list *wl = (struct tui_list*)w;
192 assert(wl->type == TUI_LIST);
195 cmpfunc = (int (*)(const void*, const void*))strcmp;
198 nelem = darr_size(wl->entries);
199 qsort(wl->entries, nelem, sizeof *wl->entries, cmpfunc);
202 tui_call_callback(w, TUI_ONMODIFY);
205 static void draw_list(struct tui_widget *w, void *cls)
207 int i, x, y, num, idx;
208 struct tui_list *wl = (struct tui_list*)w;
210 tui_wtoscr(w, 0, 0, &x, &y);
212 tg_bgcolor(TGFX_BLUE);
213 tg_fgcolor(TGFX_CYAN);
214 tg_rect(wl->title, x, y, wl->width, wl->height, TGFX_FRAME);
216 num = darr_size(wl->entries);
217 if(num > wl->height - 2) {
218 num = wl->height - 2;
222 for(i=0; i<num; i++) {
223 idx = i + wl->view_offs;
224 if(w->focus && idx == wl->sel) {
225 tg_bgcolor(TGFX_CYAN);
226 tg_fgcolor(TGFX_BLUE);
228 tg_rect(0, x, ++y, wl->width-2, 1, 0);
229 tg_text(x, y, "%s", wl->entries[idx]);
231 tg_bgcolor(TGFX_BLUE);
232 tg_fgcolor(TGFX_CYAN);
234 tg_text(x, ++y, "%s", wl->entries[idx]);