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 <calcurse@cryptocrack.de>
This commit is contained in:
parent
7184da0fa3
commit
27b39a56ef
@ -23,6 +23,7 @@ calcurse_SOURCES = \
|
||||
ical.c \
|
||||
io.c \
|
||||
keys.c \
|
||||
listbox.c \
|
||||
llist.c \
|
||||
note.c \
|
||||
notify.c \
|
||||
|
@ -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);
|
||||
|
138
src/listbox.c
Normal file
138
src/listbox.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Calcurse - text-based organizer
|
||||
*
|
||||
* Copyright (c) 2004-2014 calcurse Development Team <misc@calcurse.org>
|
||||
* 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user