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