imtk

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