X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ftui_list.c;h=728522e0d76155995a49c55231d75bab44b265f5;hb=e0c59f7f4ddb73390dc9c16569254c0e2a921931;hp=4111d849dcee3aa617d61f06b869d008bd30d569;hpb=e8982df3e97d30c1f339d71f2eef924931a11040;p=oftp diff --git a/src/tui_list.c b/src/tui_list.c index 4111d84..728522e 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,164 @@ 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; } 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; +} + +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); +} + +int tui_list_select(struct tui_widget *w, int idx) +{ + int offs, nelem; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + if(idx == wl->sel) { + return 0; /* no change */ + } + + 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 + wl->height) { + offs = idx - wl->height / 2; + if(offs + wl->height >= nelem) { + offs = nelem - wl->height; + } + if(offs < 0) { + offs = 0; + } + wl->view_offs = offs; + } + + wl->dirty = 1; + return 0; +} + +int tui_get_list_sel(struct tui_widget *w) +{ + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + return wl->sel; +} + +int tui_list_sel_next(struct tui_widget *w) +{ + int nelem; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + nelem = darr_size(wl->entries); + + if(wl->sel + 1 >= nelem) { + return -1; + } + + if(++wl->sel - wl->view_offs >= wl->height) { + wl->view_offs = wl->sel - wl->height; + } + wl->dirty = 1; + 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; + return 0; +} + +int tui_list_sel_start(struct tui_widget *w) +{ struct tui_list *wl = (struct tui_list*)w; assert(wl->type == TUI_LIST); - darr_push(wl->entries, &text); + + wl->sel = 0; + wl->view_offs = 0; + wl->dirty = 1; + return 0; +} + +int tui_list_sel_end(struct tui_widget *w) +{ + int nelem; + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + nelem = darr_size(wl->entries); + + wl->sel = nelem - 1; + wl->view_offs = nelem - wl->height; + if(wl->view_offs < 0) wl->view_offs = 0; + wl->dirty = 1; + return 0; +} + +void tui_sort_list(struct tui_widget *w, int (*cmpfunc)(const void*, const void*)) +{ + struct tui_list *wl = (struct tui_list*)w; + assert(wl->type == TUI_LIST); + + if(!cmpfunc) { + cmpfunc = (int (*)(const void*, const void*))strcmp; + } + qsort(wl->entries, darr_size(wl->entries), sizeof *wl->entries, cmpfunc); } 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 +205,18 @@ static void draw_list(struct tui_widget *w, void *cls) x++; for(i=0; ientries[i]); + idx = i + wl->view_offs; + if(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]); + } } }