rayfract

annotate src/imtk/listbox.c @ 10:1496aae2e7d4

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