imtk

annotate src/listbox.c @ 27:48e708baa7be

added predicate imtk_layout_contains(x, y)
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 12 Dec 2020 17:20:00 +0200
parents 11da537aeba6
children
rev   line source
nuclear@17 1 #include <string.h>
nuclear@17 2 #include <stdarg.h>
nuclear@17 3 #include <assert.h>
nuclear@17 4 #include "imtk.h"
nuclear@17 5 #include "state.h"
nuclear@17 6 #include "draw.h"
nuclear@17 7
nuclear@17 8 #define ITEM_HEIGHT 18
nuclear@17 9 #define PAD 3
nuclear@17 10
nuclear@18 11 static int list_radio(int id, const char *list, int sel, int x, int y, void (*draw)());
nuclear@17 12 static void draw_listbox(int id, const char *list, int sel, int x, int y, int width, int nitems, int over);
nuclear@18 13 static void draw_radio(int id, const char *list, int sel, int x, int y, int width, int nitems, int over);
nuclear@17 14
nuclear@17 15 int imtk_listbox(int id, const char *list, int sel, int x, int y)
nuclear@17 16 {
nuclear@18 17 return list_radio(id, list, sel, x, y, draw_listbox);
nuclear@18 18 }
nuclear@18 19
nuclear@18 20 int imtk_radiogroup(int id, const char *list, int sel, int x, int y)
nuclear@18 21 {
nuclear@18 22 return list_radio(id, list, sel, x, y, draw_radio);
nuclear@18 23 }
nuclear@18 24
nuclear@18 25 static int list_radio(int id, const char *list, int sel, int x, int y, void (*draw)())
nuclear@18 26 {
nuclear@17 27 int i, max_width, nitems, over;
nuclear@17 28 const char *ptr;
nuclear@17 29
nuclear@17 30 assert(id >= 0);
nuclear@17 31
nuclear@20 32 if(x == IMTK_AUTO || y == IMTK_AUTO) {
nuclear@20 33 imtk_layout_get_pos(&x, &y);
nuclear@20 34 }
nuclear@20 35
nuclear@17 36 max_width = 0;
nuclear@17 37 over = 0;
nuclear@17 38
nuclear@17 39 ptr = list;
nuclear@17 40 for(i=0; *ptr; i++) {
nuclear@17 41 int strsz = imtk_string_size(ptr) + 2 * PAD;
nuclear@17 42 if(strsz > max_width) {
nuclear@17 43 max_width = strsz;
nuclear@17 44 }
nuclear@17 45 ptr += strlen(ptr) + 1;
nuclear@17 46
nuclear@17 47 if(imtk_hit_test(x, y + i * ITEM_HEIGHT, max_width, ITEM_HEIGHT)) {
nuclear@17 48 imtk_set_hot(id);
nuclear@17 49 over = i + 1;
nuclear@17 50 }
nuclear@17 51 }
nuclear@17 52 nitems = i;
nuclear@17 53
nuclear@17 54 if(imtk_button_state(IMTK_LEFT_BUTTON)) {
nuclear@17 55 if(over) {
nuclear@17 56 imtk_set_active(id);
nuclear@17 57 }
nuclear@17 58 } else {
nuclear@17 59 if(imtk_is_active(id)) {
nuclear@17 60 imtk_set_active(-1);
nuclear@17 61 if(imtk_is_hot(id) && over) {
nuclear@17 62 sel = over - 1;
nuclear@17 63 }
nuclear@17 64 }
nuclear@17 65 }
nuclear@17 66
nuclear@18 67 draw(id, list, sel, x, y, max_width, nitems, over);
nuclear@20 68 imtk_layout_advance(max_width, ITEM_HEIGHT * nitems);
nuclear@17 69 return sel;
nuclear@17 70 }
nuclear@17 71
nuclear@17 72 char *imtk_create_list(const char *first, ...)
nuclear@17 73 {
nuclear@17 74 int sz;
nuclear@17 75 char *buf, *item;
nuclear@17 76 va_list ap;
nuclear@17 77
nuclear@17 78 if(!first) {
nuclear@17 79 return 0;
nuclear@17 80 }
nuclear@17 81
nuclear@17 82 sz = strlen(first) + 2;
nuclear@17 83 if(!(buf = malloc(sz))) {
nuclear@17 84 return 0;
nuclear@17 85 }
nuclear@17 86 memcpy(buf, first, sz - 2);
nuclear@17 87 buf[sz - 1] = buf[sz - 2] = 0;
nuclear@17 88
nuclear@17 89 va_start(ap, first);
nuclear@17 90 while((item = va_arg(ap, char*))) {
nuclear@17 91 int len = strlen(item);
nuclear@17 92 char *tmp = realloc(buf, sz + len + 1);
nuclear@17 93 if(!tmp) {
nuclear@17 94 free(buf);
nuclear@17 95 return 0;
nuclear@17 96 }
nuclear@17 97 buf = tmp;
nuclear@17 98
nuclear@17 99 memcpy(buf + sz - 1, item, len);
nuclear@17 100 sz += len + 1;
nuclear@17 101 buf[sz - 1] = buf[sz - 2] = 0;
nuclear@17 102 }
nuclear@17 103 va_end(ap);
nuclear@17 104
nuclear@17 105 return buf;
nuclear@17 106 }
nuclear@17 107
nuclear@17 108 void imtk_free_list(char *list)
nuclear@17 109 {
nuclear@17 110 free(list);
nuclear@17 111 }
nuclear@17 112
nuclear@17 113 static void draw_listbox(int id, const char *list, int sel, int x, int y, int width, int nitems, int over)
nuclear@17 114 {
nuclear@17 115 int i;
nuclear@17 116 const char *item = list;
nuclear@17 117
nuclear@17 118 glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
nuclear@17 119
nuclear@17 120 for(i=0; i<nitems; i++) {
nuclear@17 121 int item_y = i * ITEM_HEIGHT + y;
nuclear@17 122 unsigned int attr = 0;
nuclear@17 123 float tcol[4], bcol[4];
nuclear@17 124
nuclear@17 125 if(over - 1 == i) {
nuclear@17 126 attr |= IMTK_FOCUS_BIT;
nuclear@17 127 }
nuclear@17 128
nuclear@17 129 if(sel == i) {
nuclear@17 130 attr |= IMTK_SEL_BIT;
nuclear@17 131 memcpy(tcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof tcol);
nuclear@17 132 memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
nuclear@17 133 } else {
nuclear@17 134 memcpy(tcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof tcol);
nuclear@17 135 memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
nuclear@17 136 }
nuclear@17 137
nuclear@17 138 imtk_draw_rect(x, item_y, width, ITEM_HEIGHT, tcol, bcol);
nuclear@17 139
nuclear@17 140 glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
nuclear@17 141 imtk_draw_string(x + 3, item_y + ITEM_HEIGHT - 5, item);
nuclear@17 142 item += strlen(item) + 1;
nuclear@17 143 }
nuclear@17 144
nuclear@17 145 imtk_draw_frame(x, y, width, ITEM_HEIGHT * nitems, FRAME_INSET);
nuclear@17 146 }
nuclear@18 147
nuclear@18 148 static void draw_radio(int id, const char *list, int sel, int x, int y, int width, int nitems, int over)
nuclear@18 149 {
nuclear@18 150 int i;
nuclear@18 151 const char *item = list;
nuclear@18 152 float rad = ITEM_HEIGHT * 0.5;
nuclear@18 153
nuclear@18 154 for(i=0; i<nitems; i++) {
nuclear@18 155 int item_y = i * ITEM_HEIGHT + y;
nuclear@18 156 unsigned int attr = 0;
nuclear@18 157 float tcol[4], bcol[4];
nuclear@18 158
nuclear@18 159 if(over - 1 == i) {
nuclear@18 160 attr |= IMTK_FOCUS_BIT;
nuclear@18 161 }
nuclear@18 162
nuclear@19 163 imtk_draw_disc_frame(x + rad, item_y + rad, rad * 0.9, rad * 0.75, 5, FRAME_INSET);
nuclear@19 164
nuclear@18 165 memcpy(tcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof tcol);
nuclear@18 166 memcpy(bcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof bcol);
nuclear@19 167 imtk_draw_disc(x + rad, item_y + rad, rad * 0.75, 5, tcol, bcol);
nuclear@18 168
nuclear@18 169 if(i == sel) {
nuclear@18 170 attr |= IMTK_SEL_BIT;
nuclear@18 171 memcpy(tcol, imtk_get_color(IMTK_TOP_COLOR | attr), sizeof tcol);
nuclear@18 172 memcpy(bcol, imtk_get_color(IMTK_BOTTOM_COLOR | attr), sizeof bcol);
nuclear@19 173
nuclear@18 174 imtk_draw_disc(x + rad, item_y + ITEM_HEIGHT / 2, rad * 0.6, 5, tcol, bcol);
nuclear@18 175 }
nuclear@18 176
nuclear@18 177 glColor4fv(imtk_get_color(IMTK_TEXT_COLOR));
nuclear@18 178 imtk_draw_string(x + rad * 2.0 + 3, item_y + ITEM_HEIGHT - 5, item);
nuclear@18 179 item += strlen(item) + 1;
nuclear@18 180 }
nuclear@18 181 }