From 2a15531bb9df283060e0eb0e7e93ecf33e494b4d Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Sun, 18 May 2014 09:47:19 +0200 Subject: Add support for caption rows in list boxes This adds support for rows that cannot be selected. Such rows can be used for section headings and the like. Signed-off-by: Lukas Fleischer --- src/calcurse.h | 16 +++++++++++-- src/custom.c | 9 ++++++-- src/listbox.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/notify.c | 9 +++++++- src/ui-day.c | 5 +++++ src/ui-todo.c | 5 +++++ src/wins.c | 6 +++-- 7 files changed, 105 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/calcurse.h b/src/calcurse.h index 07f6b78..8072304 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -511,13 +511,21 @@ struct scrollwin { }; /* Generic list box structure. */ +enum listbox_row_type { + LISTBOX_ROW_TEXT, + LISTBOX_ROW_CAPTION +}; + +typedef enum listbox_row_type (*listbox_fn_item_type_t) (int, void *); typedef int (*listbox_fn_item_height_t) (int, void *); typedef void (*listbox_fn_draw_item_t) (int, WINDOW *, int, int, void *); struct listbox { struct scrollwin sw; unsigned item_count; - unsigned item_sel; + int item_sel; + listbox_fn_item_type_t fn_type; + enum listbox_row_type *type; listbox_fn_item_height_t fn_height; unsigned *ch; listbox_fn_draw_item_t fn_draw; @@ -793,7 +801,9 @@ int keys_check_missing_bindings(void); void keys_fill_missing(void); /* listbox.c */ -void listbox_init(struct listbox *, int, int, int, int, const char *, listbox_fn_item_height_t, listbox_fn_draw_item_t); +void listbox_init(struct listbox *, int, int, int, int, const char *, + listbox_fn_item_type_t, listbox_fn_item_height_t, + listbox_fn_draw_item_t); void listbox_delete(struct listbox *); void listbox_resize(struct listbox *, int, int, int, int); void listbox_set_cb_data(struct listbox *, void *); @@ -951,6 +961,7 @@ void ui_day_load_items(void); void ui_day_sel_reset(void); void ui_day_sel_move(int); void ui_day_draw(int, WINDOW *, int, int, void *); +enum listbox_row_type ui_day_row_type(int, void *); int ui_day_height(int, void *); void ui_day_update_panel(int); void ui_day_popup_item(void); @@ -964,6 +975,7 @@ void ui_todo_delete(void); void ui_todo_edit(void); void ui_todo_pipe(void); void ui_todo_draw(int, WINDOW *, int, int, void *); +enum listbox_row_type ui_todo_row_type(int, void *); int ui_todo_height(int, void *); void ui_todo_load_items(void); void ui_todo_sel_move(int); diff --git a/src/custom.c b/src/custom.c index bb425a6..688ca21 100644 --- a/src/custom.c +++ b/src/custom.c @@ -684,6 +684,11 @@ static void print_general_option(int i, WINDOW *win, int y, int hilt, void *cb_d custom_remove_attr(win, ATTR_HIGHEST); } +static enum listbox_row_type general_option_row_type(int i, void *cb_data) +{ + return LISTBOX_ROW_TEXT; +} + static int general_option_height(int i, void *cb_data) { if (i == 9) @@ -771,8 +776,8 @@ void custom_general_config(void) clear(); listbox_init(&lb, 0, 0, notify_bar() ? row - 3 : row - 2, col, - _("general options"), general_option_height, - print_general_option); + _("general options"), general_option_row_type, + general_option_height, print_general_option); listbox_load_items(&lb, 10); listbox_draw_deco(&lb, 0); status_mesg("", ""); diff --git a/src/listbox.c b/src/listbox.c index 80b5dae..245eeef 100644 --- a/src/listbox.c +++ b/src/listbox.c @@ -37,12 +37,15 @@ #include "calcurse.h" void listbox_init(struct listbox *lb, int y, int x, int h, int w, - const char *label, listbox_fn_item_height_t fn_height, + const char *label, listbox_fn_item_type_t fn_type, + listbox_fn_item_height_t fn_height, listbox_fn_draw_item_t fn_draw) { EXIT_IF(lb == NULL, "null pointer"); wins_scrollwin_init(&(lb->sw), y, x, h, w, label); lb->item_count = lb->item_sel = 0; + lb->fn_type = fn_type; + lb->type = NULL; lb->fn_height = fn_height; lb->ch = NULL; lb->fn_draw = fn_draw; @@ -53,6 +56,7 @@ void listbox_delete(struct listbox *lb) { EXIT_IF(lb == NULL, "null pointer"); wins_scrollwin_delete(&(lb->sw)); + free(lb->type); free(lb->ch); } @@ -78,9 +82,15 @@ void listbox_load_items(struct listbox *lb, int item_count) if (lb->item_sel >= item_count) lb->item_sel = item_count - 1; + if (item_count == 0) + return; + + free(lb->type); free(lb->ch); + lb->type = xmalloc(item_count * sizeof(unsigned)); lb->ch = xmalloc((item_count + 1) * sizeof(unsigned)); for (i = 0, ch = 0; i < item_count; i++) { + lb->type[i] = lb->fn_type(i, lb->cb_data); lb->ch[i] = ch; ch += lb->fn_height(i, lb->cb_data); } @@ -113,12 +123,53 @@ int listbox_get_sel(struct listbox *lb) return lb->item_sel; } -void listbox_set_sel(struct listbox *lb, unsigned pos) +static void listbox_fix_sel(struct listbox *lb, int direction) { - lb->item_sel = pos; + int did_flip = 0; + + if (lb->item_count == 0 || direction == 0) + return; + + direction = direction > 0 ? 1 : -1; + + while (lb->type[lb->item_sel] != LISTBOX_ROW_TEXT) { + if ((direction == -1 && lb->item_sel == 0) || + (direction == 1 && lb->item_sel == lb->item_count - 1)) { + if (did_flip) { + lb->item_sel = -1; + return; + } + direction = -direction; + did_flip = 1; + } else { + lb->item_sel += direction; + } + } +} + +static void listbox_fix_visible_region(struct listbox *lb) +{ + int i; wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]); wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1); + + i = lb->item_sel - 1; + while (i >= 0 && lb->type[i] != LISTBOX_ROW_TEXT) { + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[i]); + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[i + 1] - 1); + i++; + } +} + +void listbox_set_sel(struct listbox *lb, unsigned pos) +{ + lb->item_sel = pos; + listbox_fix_sel(lb, 1); + if (lb->item_sel < 0) + return; + + listbox_fix_visible_region(lb); } void listbox_sel_move(struct listbox *lb, int delta) @@ -126,13 +177,15 @@ void listbox_sel_move(struct listbox *lb, int delta) if (lb->item_count == 0) return; - if (delta < 0 && lb->item_sel < -delta) + lb->item_sel += delta; + if (lb->item_sel < 0) lb->item_sel = 0; - else if (delta > 0 && lb->item_sel + delta >= lb->item_count) + else if (lb->item_sel >= lb->item_count) lb->item_sel = lb->item_count - 1; - else - lb->item_sel += delta; - wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]); - wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1); + listbox_fix_sel(lb, delta); + if (lb->item_sel < 0) + return; + + listbox_fix_visible_region(lb); } diff --git a/src/notify.c b/src/notify.c index 1adaded..532bd01 100644 --- a/src/notify.c +++ b/src/notify.c @@ -658,6 +658,11 @@ static void print_config_option(int i, WINDOW *win, int y, int hilt, void *cb_da custom_remove_attr(win, ATTR_HIGHEST); } +static enum listbox_row_type config_option_row_type(int i, void *cb_data) +{ + return LISTBOX_ROW_TEXT; +} + static int config_option_height(int i, void *cb_data) { return 3; @@ -761,7 +766,9 @@ void notify_config_bar(void) int ch; clear(); - listbox_init(&lb, 0, 0, notify_bar() ? row - 3 : row - 2, col, _("notification options"), config_option_height, print_config_option); + listbox_init(&lb, 0, 0, notify_bar() ? row - 3 : row - 2, col, + _("notification options"), config_option_row_type, + config_option_height, print_config_option); listbox_load_items(&lb, 8); listbox_draw_deco(&lb, 0); status_mesg("", ""); diff --git a/src/ui-day.c b/src/ui-day.c index d1e5843..e52b6d2 100644 --- a/src/ui-day.c +++ b/src/ui-day.c @@ -843,6 +843,11 @@ void ui_day_draw(int n, WINDOW *win, int y, int hilt, void *cb_data) } +enum listbox_row_type ui_day_row_type(int i, void *cb_data) +{ + return LISTBOX_ROW_TEXT; +} + int ui_day_height(int n, void *cb_data) { struct day_item *item = day_get_item(n); diff --git a/src/ui-todo.c b/src/ui-todo.c index c7b29f4..8daf283 100644 --- a/src/ui-todo.c +++ b/src/ui-todo.c @@ -177,6 +177,11 @@ void ui_todo_draw(int n, WINDOW *win, int y, int hilt, void *cb_data) *((llist_item_t **)cb_data) = i->next; } +enum listbox_row_type ui_todo_row_type(int i, void *cb_data) +{ + return LISTBOX_ROW_TEXT; +} + int ui_todo_height(int n, void *cb_data) { return 1; diff --git a/src/wins.c b/src/wins.c index 729e014..0c12d8e 100644 --- a/src/wins.c +++ b/src/wins.c @@ -250,11 +250,13 @@ static void wins_init_panels(void) wins_sbar_width(), _("Calendar")); listbox_init(&lb_apt, win[APP].y, win[APP].x, win[APP].h, win[APP].w, - _("Appointments"), ui_day_height, ui_day_draw); + _("Appointments"), ui_day_row_type, ui_day_height, + ui_day_draw); ui_day_load_items(); listbox_init(&lb_todo, win[TOD].y, win[TOD].x, win[TOD].h, win[TOD].w, - _("TODO"), ui_todo_height, ui_todo_draw); + _("TODO"), ui_todo_row_type, ui_todo_height, + ui_todo_draw); ui_todo_load_items(); } -- cgit v1.2.3-70-g09d2