X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ftui_list.c;h=42551eaefedaee78ee79acd7e1a82f4c24b5d8a2;hb=8b4d2adf48213f2bf74ca1a423b1ac3dc8066f95;hp=4111d849dcee3aa617d61f06b869d008bd30d569;hpb=2ba6401e39bcfaaccaa45e6b7ef780a7a15b0c48;p=oftp diff --git a/src/tui_list.c b/src/tui_list.c index 4111d84..42551ea 100644 --- a/src/tui_list.c +++ b/src/tui_list.c @@ -5,6 +5,7 @@ #include "tui.h" #include "tuipriv.h" #include "tgfx.h" +#include "util.h" static void free_list(struct tui_widget *w, void *cls); static void draw_list(struct tui_widget *w, void *cls); @@ -24,6 +25,8 @@ struct tui_widget *tui_list(const char *title, int x, int y, int width, int heig w->height = height; w->entries = darr_alloc(0, sizeof *w->entries); + w->sel = -1; + w->dirty = 1; if(cbfunc) { tui_set_callback((struct tui_widget*)w, TUI_ONMODIFY, cbfunc, cbdata); @@ -35,32 +38,186 @@ struct tui_widget *tui_list(const char *title, int x, int y, int width, int heig static void free_list(struct tui_widget *w, void *cls) { - darr_free(((struct tui_list*)w)->entries); + struct tui_list *wl = (struct tui_list*)w; + + tui_clear_list(w); + darr_free(wl->entries); } void tui_clear_list(struct tui_widget *w) { + int i; struct tui_list *wl = (struct tui_list*)w; assert(wl->type == TUI_LIST); + + for(i=0; ientries); i++) { + free(wl->entries[i]); + } darr_clear(wl->entries); + wl->dirty = 1; + + tui_call_callback(w, TUI_ONMODIFY); } void tui_add_list_item(struct tui_widget *w, const char *text) { + char *str; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + str = strdup_nf(text); + darr_push(wl->entries, &str); + wl->dirty = 1; + + tui_call_callback(w, TUI_ONMODIFY); +} + +int tui_num_list_items(struct tui_widget *w) +{ + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + return darr_size(wl->entries); +} + +#define VISLINES(wl) ((wl)->height - 2) + +int tui_list_select(struct tui_widget *w, int idx) +{ + int offs, nelem, numvis; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + if(idx == wl->sel) { + return 0; /* no change */ + } + + numvis = VISLINES(wl); + + if(idx < 0) { + wl->sel = -1; + return 0; + } + if(idx >= (nelem = darr_size(wl->entries))) { + return -1; + } + wl->sel = idx; + + if(idx < wl->view_offs || idx >= wl->view_offs + numvis) { + offs = idx - numvis / 2; + if(offs + numvis >= nelem) { + offs = nelem - numvis; + } + if(offs < 0) { + offs = 0; + } + wl->view_offs = offs; + } + + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); + return 0; +} + +int tui_get_list_sel(struct tui_widget *w) +{ struct tui_list *wl = (struct tui_list*)w; assert(wl->type == TUI_LIST); - darr_push(wl->entries, &text); + return wl->sel; +} + +int tui_list_sel_next(struct tui_widget *w) +{ + int nelem, numvis; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + nelem = darr_size(wl->entries); + + numvis = VISLINES(wl); + + if(wl->sel + 1 >= nelem) { + return -1; + } + + if(++wl->sel - wl->view_offs >= numvis) { + wl->view_offs = wl->sel - numvis + 1; + } + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); + return 0; +} + +int tui_list_sel_prev(struct tui_widget *w) +{ + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + if(wl->sel <= 0) { + return -1; + } + if(--wl->sel < wl->view_offs) { + wl->view_offs = wl->sel; + } + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); + return 0; +} + +int tui_list_sel_start(struct tui_widget *w) +{ + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + wl->sel = 0; + wl->view_offs = 0; + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); + return 0; +} + +int tui_list_sel_end(struct tui_widget *w) +{ + int nelem, numvis; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + nelem = darr_size(wl->entries); + numvis = VISLINES(wl); + + wl->sel = nelem - 1; + wl->view_offs = nelem - numvis; + if(wl->view_offs < 0) wl->view_offs = 0; + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); + return 0; +} + +void tui_sort_list(struct tui_widget *w, int (*cmpfunc)(const void*, const void*)) +{ + int nelem; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + if(!cmpfunc) { + cmpfunc = (int (*)(const void*, const void*))strcmp; + } + + nelem = darr_size(wl->entries); + qsort(wl->entries, nelem, sizeof *wl->entries, cmpfunc); + + wl->dirty = 1; + tui_call_callback(w, TUI_ONMODIFY); } static void draw_list(struct tui_widget *w, void *cls) { - int i, x, y, num; + int i, x, y, num, idx; struct tui_list *wl = (struct tui_list*)w; tui_wtoscr(w, 0, 0, &x, &y); tg_bgcolor(TGFX_BLUE); + tg_fgcolor(TGFX_CYAN); tg_rect(wl->title, x, y, wl->width, wl->height, TGFX_FRAME); num = darr_size(wl->entries); @@ -70,6 +227,18 @@ static void draw_list(struct tui_widget *w, void *cls) x++; for(i=0; ientries[i]); + idx = i + wl->view_offs; + if(w->focus && idx == wl->sel) { + tg_bgcolor(TGFX_CYAN); + tg_fgcolor(TGFX_BLUE); + + tg_rect(0, x, ++y, wl->width-2, 1, 0); + tg_text(x, y, "%s", wl->entries[idx]); + + tg_bgcolor(TGFX_BLUE); + tg_fgcolor(TGFX_CYAN); + } else { + tg_text(x, ++y, "%s", wl->entries[idx]); + } } }