glamtk

view src/imtk.c @ 1:dfbd12d1f566

finished the checkbox control, did some reorg as well.
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 30 Dec 2010 15:10:25 +0200
parents b04d49e4599c
children 3d661dd17af3
line source
1 #include <stdio.h>
2 #include <string.h>
3 #include <assert.h>
4 #ifndef __APPLE__
5 #include <GL/glut.h>
6 #else
7 #include <GLUT/glut.h>
8 #endif
9 #include "imtk.h"
11 #define CHECKBOX_SIZE 14
13 enum {
14 FRAME_OUTSET,
15 FRAME_INSET
16 };
18 /* default colors, can be changed with imtk_set_color */
19 static float colors[][4] = {
20 {0.0, 0.0, 0.0}, /* text color */
21 {0.7, 0.7, 0.7}, /* base color */
22 {0.85, 0.85, 0.85}, /* focus color */
23 {1.0, 1.0, 1.0}, /* lit bevel */
24 {0.3, 0.3, 0.3} /* shadowed bevel */
25 };
27 static int scr_width = 1, scr_height = 1;
28 static int mousex, mousey, mouse_bnmask;
29 static int active = -1, hot = -1;
31 static void set_active(int id);
32 static int set_hot(int id);
33 static int hit_test(int x, int y, int w, int h);
35 static void draw_button(int id, const char *label, int x, int y);
36 static void calc_button_size(const char *label, int *wret, int *hret);
37 static void draw_checkbox(int id, const char *label, int x, int y, int state);
38 static void draw_string(int x, int y, const char *str);
39 static int string_size(const char *str);
40 static void draw_frame(int x, int y, int w, int h, int style);
42 void imtk_set_color(int col, float r, float g, float b)
43 {
44 assert(col >= 0 && col < sizeof colors / sizeof *colors);
46 colors[col][0] = r;
47 colors[col][1] = g;
48 colors[col][2] = b;
49 }
51 void imtk_inp_key(int key, int state)
52 {
53 glutPostRedisplay();
54 }
56 void imtk_inp_mouse(int bn, int state)
57 {
58 if(state == IMTK_DOWN) {
59 mouse_bnmask |= 1 << bn;
60 } else {
61 mouse_bnmask &= ~(1 << bn);
62 }
63 glutPostRedisplay();
64 }
66 void imtk_inp_motion(int x, int y)
67 {
68 mousex = x;
69 mousey = y;
71 glutPostRedisplay();
72 }
74 void imtk_inp_reshape(int x, int y)
75 {
76 scr_width = x;
77 scr_height = y;
78 }
80 void imtk_begin(void)
81 {
82 glMatrixMode(GL_PROJECTION);
83 glPushMatrix();
84 glLoadIdentity();
85 glTranslatef(-1, 1, 0);
86 glScalef(2.0 / scr_width, -2.0 / scr_height, 1.0);
87 }
89 void imtk_end(void)
90 {
91 glMatrixMode(GL_PROJECTION);
92 glPopMatrix();
93 }
95 int imtk_button(int id, const char *label, int x, int y)
96 {
97 int w, h, res = 0;
98 int over = 0;
100 assert(id >= 0);
102 calc_button_size(label, &w, &h);
104 if(hit_test(x, y, w, h)) {
105 set_hot(id);
106 over = 1;
107 }
109 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
110 if(over) {
111 set_active(id);
112 }
113 } else { /* mouse button up */
114 if(active == id) {
115 set_active(-1);
116 if(hot == id && over) {
117 res = 1;
118 }
119 }
120 }
122 draw_button(id, label, x, y);
123 return res;
124 }
126 int imtk_checkbox(int id, const char *label, int x, int y, int state)
127 {
128 int sz = CHECKBOX_SIZE;
129 int over = 0;
131 assert(id >= 0);
133 if(hit_test(x, y, sz, sz)) {
134 set_hot(id);
135 over = 1;
136 }
138 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
139 if(over) {
140 set_active(id);
141 }
142 } else { /* mouse button up */
143 if(active == id) {
144 set_active(-1);
145 if(hot == id && over) {
146 state = !state;
147 }
148 }
149 }
151 draw_checkbox(id, label, x, y, state);
152 return state;
153 }
155 static void set_active(int id)
156 {
157 active = id;
158 }
160 static int set_hot(int id)
161 {
162 if(active == -1) {
163 hot = id;
164 return 1;
165 }
166 return 0;
167 }
169 static int hit_test(int x, int y, int w, int h)
170 {
171 return mousex >= x && mousex < (x + w) &&
172 mousey >= y && mousey < (y + h);
173 }
175 static void draw_button(int id, const char *label, int x, int y)
176 {
177 int width, height;
179 calc_button_size(label, &width, &height);
181 glBegin(GL_QUADS);
182 if(hit_test(x, y, width, height)) {
183 glColor3fv(colors[IMTK_FOCUS_COLOR]);
184 } else {
185 glColor3fv(colors[IMTK_BASE_COLOR]);
186 }
187 glVertex2f(x, y);
188 glVertex2f(x + width, y);
189 glVertex2f(x + width, y + height);
190 glVertex2f(x, y + height);
191 glEnd();
193 draw_frame(x, y, width, height, active == id ? FRAME_INSET : FRAME_OUTSET);
195 glColor3fv(colors[IMTK_TEXT_COLOR]);
196 draw_string(x + 20, y + 15, label);
197 }
199 static void calc_button_size(const char *label, int *wret, int *hret)
200 {
201 int strsz = string_size(label);
202 if(wret) *wret = strsz + 40;
203 if(hret) *hret = 20;
204 }
206 static void draw_checkbox(int id, const char *label, int x, int y, int state)
207 {
208 static const int sz = CHECKBOX_SIZE;
210 if(hit_test(x, y, sz, sz)) {
211 glColor3fv(colors[IMTK_FOCUS_COLOR]);
212 } else {
213 glColor3fv(colors[IMTK_BASE_COLOR]);
214 }
216 glBegin(GL_QUADS);
217 glVertex2f(x, y);
218 glVertex2f(x + sz, y);
219 glVertex2f(x + sz, y + sz);
220 glVertex2f(x, y + sz);
221 glEnd();
223 draw_frame(x, y, sz, sz, FRAME_INSET);
225 glColor3fv(colors[IMTK_TEXT_COLOR]);
226 if(state) {
227 glPushAttrib(GL_LINE_BIT);
228 glLineWidth(2);
230 glBegin(GL_LINES);
231 glVertex2f(x + 2, y + 2);
232 glVertex2f(x + sz - 2, y + sz - 2);
233 glVertex2f(x + sz - 2, y + 2);
234 glVertex2f(x + 2, y + sz - 2);
235 glEnd();
237 glPopAttrib();
238 }
240 draw_string(x + sz + 5, y + sz - 2, label);
241 }
243 static void draw_string(int x, int y, const char *str)
244 {
245 glRasterPos2i(x, y);
246 while(*str) {
247 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *str++);
248 }
249 }
251 static int string_size(const char *str)
252 {
253 return glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)str);
254 }
256 static void draw_frame(int x, int y, int w, int h, int style)
257 {
258 float tcol[3], bcol[3];
260 switch(style) {
261 case FRAME_INSET:
262 memcpy(tcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof tcol);
263 memcpy(bcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof bcol);
264 break;
266 case FRAME_OUTSET:
267 default:
268 memcpy(tcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof tcol);
269 memcpy(bcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof bcol);
270 }
272 glBegin(GL_LINES);
273 glColor3fv(tcol);
274 glVertex2f(x, y + h);
275 glVertex2f(x, y);
276 glVertex2f(x, y);
277 glVertex2f(x + w, y);
278 glColor3fv(bcol);
279 glVertex2f(x + w, y);
280 glVertex2f(x + w, y + h);
281 glVertex2f(x + w, y + h);
282 glVertex2f(x, y + h);
283 glEnd();
284 }