From 27b39a56ef8a2cf94ace5911614d0bd63c26ba06 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Tue, 13 May 2014 20:30:02 +0200 Subject: Add a generic list box implementation This adds a very generic list box implementation. List boxes with items of different heights are supported. Two callback functions to determine the height of every single item and to draw a specific item are used. Signed-off-by: Lukas Fleischer --- src/Makefile.am | 1 + src/calcurse.h | 26 +++++++++++ src/listbox.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 src/listbox.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 3559a25..d17da42 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ calcurse_SOURCES = \ ical.c \ io.c \ keys.c \ + listbox.c \ llist.c \ note.c \ notify.c \ diff --git a/src/calcurse.h b/src/calcurse.h index 53610c4..4f5c2c0 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -515,6 +515,20 @@ struct scrollwin { const char *label; }; +/* Generic list box structure. */ +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; + listbox_fn_item_height_t fn_height; + unsigned *ch; + listbox_fn_draw_item_t fn_draw; + void *cb_data; +}; + /* Pad structure to handle scrolling. */ struct pad { int width; @@ -802,6 +816,18 @@ void keys_save_bindings(FILE *); 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_delete(struct listbox *); +void listbox_resize(struct listbox *, int, int, int, int); +void listbox_set_cb_data(struct listbox *, void *); +void listbox_load_items(struct listbox *, int); +void listbox_draw_deco(struct listbox *); +void listbox_display(struct listbox *); +int listbox_get_sel(struct listbox *); +void listbox_set_sel(struct listbox *, unsigned); +void listbox_sel_move(struct listbox *, int); + /* mem.c */ void *xmalloc(size_t); void *xcalloc(size_t, size_t); diff --git a/src/listbox.c b/src/listbox.c new file mode 100644 index 0000000..3a31017 --- /dev/null +++ b/src/listbox.c @@ -0,0 +1,138 @@ +/* + * Calcurse - text-based organizer + * + * Copyright (c) 2004-2014 calcurse Development Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Send your feedback or comments to : misc@calcurse.org + * Calcurse home page : http://calcurse.org + * + */ + +#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, + 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_height = fn_height; + lb->ch = NULL; + lb->fn_draw = fn_draw; + lb->cb_data = NULL; +} + +void listbox_delete(struct listbox *lb) +{ + EXIT_IF(lb == NULL, "null pointer"); + wins_scrollwin_delete(&(lb->sw)); + free(lb->ch); +} + +void listbox_resize(struct listbox *lb, int y, int x, int h, int w) +{ + EXIT_IF(lb == NULL, "null pointer"); + wins_scrollwin_resize(&(lb->sw), y, x, h, w); + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]); + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1); +} + +void listbox_set_cb_data(struct listbox *lb, void *cb_data) +{ + lb->cb_data = cb_data; +} + +void listbox_load_items(struct listbox *lb, int item_count) +{ + int i, ch; + + lb->item_count = item_count; + + if (lb->item_sel >= item_count) + lb->item_sel = item_count - 1; + + free(lb->ch); + lb->ch = xmalloc((item_count + 1) * sizeof(unsigned)); + for (i = 0, ch = 0; i < item_count; i++) { + lb->ch[i] = ch; + ch += lb->fn_height(i, lb->cb_data); + } + lb->ch[item_count] = ch; + + wins_scrollwin_set_linecount(&(lb->sw), ch); +} + +void listbox_draw_deco(struct listbox *lb) +{ + wins_scrollwin_draw_deco(&(lb->sw)); +} + +void listbox_display(struct listbox *lb) +{ + int i; + + werase(lb->sw.inner); + + for (i = 0; i < lb->item_count; i++) { + int is_sel = (i == lb->item_sel); + lb->fn_draw(i, lb->sw.inner, lb->ch[i], is_sel, lb->cb_data); + } + + wins_scrollwin_display(&(lb->sw)); +} + +int listbox_get_sel(struct listbox *lb) +{ + return lb->item_sel; +} + +void listbox_set_sel(struct listbox *lb, unsigned pos) +{ + lb->item_sel = pos; + + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel]); + wins_scrollwin_ensure_visible(&(lb->sw), lb->ch[lb->item_sel + 1] - 1); +} + +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 = 0; + else if (delta > 0 && lb->item_sel + delta >= 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); +} -- cgit v1.2.3-70-g09d2