- added libdrawtext
[demo_prior] / src / imtk / listbox.c
diff --git a/src/imtk/listbox.c b/src/imtk/listbox.c
new file mode 100644 (file)
index 0000000..74dd7aa
--- /dev/null
@@ -0,0 +1,181 @@
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include "imtk.h"
+#include "state.h"
+#include "draw.h"
+
+#define ITEM_HEIGHT            18
+#define PAD                            3
+
+static int list_radio(int id, const char *list, int sel, int x, int y, void (*draw)());
+static void draw_listbox(int id, const char *list, int sel, int x, int y, int width, int nitems, int over);
+static void draw_radio(int id, const char *list, int sel, int x, int y, int width, int nitems, int over);
+
+int imtk_listbox(int id, const char *list, int sel, int x, int y)
+{
+       return list_radio(id, list, sel, x, y, draw_listbox);
+}
+
+int imtk_radiogroup(int id, const char *list, int sel, int x, int y)
+{
+       return list_radio(id, list, sel, x, y, draw_radio);
+}
+
+static int list_radio(int id, const char *list, int sel, int x, int y, void (*draw)())
+{
+       int i, max_width, nitems, over;
+       const char *ptr;
+
+       assert(id >= 0);
+
+       if(x == IMTK_AUTO || y == IMTK_AUTO) {
+               imtk_layout_get_pos(&x, &y);
+       }
+
+       max_width = 0;
+       over = 0;
+
+       ptr = list;
+       for(i=0; *ptr; i++) {
+               int strsz = imtk_string_size(ptr) + 2 * PAD;
+               if(strsz > max_width) {
+                       max_width = strsz;
+               }
+               ptr += strlen(ptr) + 1;
+
+               if(imtk_hit_test(x, y + i * ITEM_HEIGHT, max_width, ITEM_HEIGHT)) {
+                       imtk_set_hot(id);
+                       over = i + 1;
+               }
+       }
+       nitems = i;
+
+       if(imtk_button_state(IMTK_LEFT_BUTTON)) {
+               if(over) {
+                       imtk_set_active(id);
+               }
+       } else {
+               if(imtk_is_active(id)) {
+                       imtk_set_active(-1);
+                       if(imtk_is_hot(id) && over) {
+                               sel = over - 1;
+                       }
+               }
+       }
+
+       draw(id, list, sel, x, y, max_width, nitems, over);
+       imtk_layout_advance(max_width, ITEM_HEIGHT * nitems);
+       return sel;
+}
+
+char *imtk_create_list(const char *first, ...)
+{
+       int sz;
+       char *buf, *item;
+       va_list ap;
+
+       if(!first) {
+               return 0;
+       }
+
+       sz = strlen(first) + 2;
+       if(!(buf = malloc(sz))) {
+               return 0;
+       }
+       memcpy(buf, first, sz - 2);
+       buf[sz - 1] = buf[sz - 2] = 0;
+
+       va_start(ap, first);
+       while((item = va_arg(ap, char*))) {
+               int len = strlen(item);
+               char *tmp = realloc(buf, sz + len + 1);
+               if(!tmp) {
+                       free(buf);
+                       return 0;
+               }
+               buf = tmp;
+
+               memcpy(buf + sz - 1, item, len);
+               sz += len + 1;
+               buf[sz - 1] = buf[sz - 2] = 0;
+       }
+       va_end(ap);
+
+       return buf;
+}
+
+void imtk_free_list(char *list)
+{
+       free(list);
+}
+
+static void draw_listbox(int id, const char *list, int sel, int x, int y, int width, int nitems, int over)
+{
+       int i;
+       const char *item = list;
+
+       glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
+
+       for(i=0; i<nitems; i++) {
+               int item_y = i * ITEM_HEIGHT + y;
+               unsigned int attr = 0;
+               float tcol[4], bcol[4];
+
+               if(over - 1 == i) {
+                       attr |= IMTK_FOCUS_BIT;
+               }
+
+               if(sel == i) {
+                       attr |= IMTK_SEL_BIT;
+                       memcpy(tcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof tcol);
+                       memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
+               } else {
+                       memcpy(tcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof tcol);
+                       memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
+               }
+
+               imtk_draw_rect(x, item_y, width, ITEM_HEIGHT, tcol, bcol);
+
+               glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
+               imtk_draw_string(x + 3, item_y + ITEM_HEIGHT - 5, item);
+               item += strlen(item) + 1;
+       }
+
+       imtk_draw_frame(x, y, width, ITEM_HEIGHT * nitems, FRAME_INSET);
+}
+
+static void draw_radio(int id, const char *list, int sel, int x, int y, int width, int nitems, int over)
+{
+       int i;
+       const char *item = list;
+       float rad = ITEM_HEIGHT * 0.5;
+
+       for(i=0; i<nitems; i++) {
+               int item_y = i * ITEM_HEIGHT + y;
+               unsigned int attr = 0;
+               float tcol[4], bcol[4];
+
+               if(over - 1 == i) {
+                       attr |= IMTK_FOCUS_BIT;
+               }
+
+               imtk_draw_disc_frame(x + rad, item_y + rad, rad * 0.9, rad * 0.75, 5, FRAME_INSET);
+
+               memcpy(tcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof tcol);
+               memcpy(bcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof bcol);
+               imtk_draw_disc(x + rad, item_y + rad, rad * 0.75, 5, tcol, bcol);
+
+               if(i == sel) {
+                       attr |= IMTK_SEL_BIT;
+                       memcpy(tcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof tcol);
+                       memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
+
+                       imtk_draw_disc(x + rad, item_y + ITEM_HEIGHT / 2, rad * 0.6, 5, tcol, bcol);
+               }
+
+               glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
+               imtk_draw_string(x + rad * 2.0 + 3, item_y + ITEM_HEIGHT - 5, item);
+               item += strlen(item) + 1;
+       }
+}