imtk

annotate src/imtk.c @ 4:00a4ea4ee6dc

attempt at slightly more complex widgets
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 05 Mar 2011 09:25:27 +0200
parents 038e5577d527
children 09b6e8a5dc14
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@2 2 #include <stdlib.h>
nuclear@1 3 #include <string.h>
nuclear@2 4 #include <ctype.h>
nuclear@4 5 #include <stdarg.h>
nuclear@0 6 #include <assert.h>
nuclear@0 7 #ifndef __APPLE__
nuclear@0 8 #include <GL/glut.h>
nuclear@0 9 #else
nuclear@0 10 #include <GLUT/glut.h>
nuclear@0 11 #endif
nuclear@0 12 #include "imtk.h"
nuclear@0 13
nuclear@1 14 #define CHECKBOX_SIZE 14
nuclear@2 15 #define TEXTBOX_SIZE 100
nuclear@3 16 #define SLIDER_SIZE 100
nuclear@3 17 #define THUMB_WIDTH 10
nuclear@3 18 #define THUMB_HEIGHT 20
nuclear@1 19
nuclear@1 20 enum {
nuclear@1 21 FRAME_OUTSET,
nuclear@1 22 FRAME_INSET
nuclear@1 23 };
nuclear@1 24
nuclear@2 25 struct key_node {
nuclear@2 26 int key;
nuclear@2 27 struct key_node *next;
nuclear@2 28 };
nuclear@2 29
nuclear@2 30 static void set_active(int id);
nuclear@2 31 static int set_hot(int id);
nuclear@2 32 static int hit_test(int x, int y, int w, int h);
nuclear@2 33
nuclear@2 34 static void draw_button(int id, const char *label, int x, int y);
nuclear@2 35 static void calc_button_size(const char *label, int *wret, int *hret);
nuclear@2 36 static void draw_checkbox(int id, const char *label, int x, int y, int state);
nuclear@2 37 static void draw_textbox(int id, const char *text, int x, int y);
nuclear@3 38 static void draw_slider(int id, float pos, float min, float max, int x, int y);
nuclear@3 39 static void draw_progress(int id, float pos, int x, int y);
nuclear@2 40 static void draw_string(int x, int y, const char *str);
nuclear@2 41 static int string_size(const char *str);
nuclear@2 42 static void draw_frame(int x, int y, int w, int h, int style);
nuclear@2 43
nuclear@2 44
nuclear@1 45 /* default colors, can be changed with imtk_set_color */
nuclear@1 46 static float colors[][4] = {
nuclear@1 47 {0.0, 0.0, 0.0}, /* text color */
nuclear@1 48 {0.7, 0.7, 0.7}, /* base color */
nuclear@1 49 {0.85, 0.85, 0.85}, /* focus color */
nuclear@1 50 {1.0, 1.0, 1.0}, /* lit bevel */
nuclear@1 51 {0.3, 0.3, 0.3} /* shadowed bevel */
nuclear@1 52 };
nuclear@1 53
nuclear@0 54 static int scr_width = 1, scr_height = 1;
nuclear@3 55 static int mousex, mousey, prevx, mouse_bnmask;
nuclear@4 56 static int active = -1, hot = -1, input = -1, prev_active = -1;
nuclear@0 57
nuclear@2 58 static struct key_node *key_list, *key_tail;
nuclear@0 59
nuclear@1 60
nuclear@1 61 void imtk_set_color(int col, float r, float g, float b)
nuclear@1 62 {
nuclear@1 63 assert(col >= 0 && col < sizeof colors / sizeof *colors);
nuclear@1 64
nuclear@1 65 colors[col][0] = r;
nuclear@1 66 colors[col][1] = g;
nuclear@1 67 colors[col][2] = b;
nuclear@1 68 }
nuclear@0 69
nuclear@0 70 void imtk_inp_key(int key, int state)
nuclear@0 71 {
nuclear@2 72 if(state == IMTK_DOWN) {
nuclear@2 73 struct key_node *node;
nuclear@2 74
nuclear@2 75 if(!(node = malloc(sizeof *node))) {
nuclear@2 76 return;
nuclear@2 77 }
nuclear@2 78 node->key = key;
nuclear@2 79 node->next = 0;
nuclear@2 80
nuclear@2 81 if(key_list) {
nuclear@2 82 key_tail->next = node;
nuclear@2 83 key_tail = node;
nuclear@2 84 } else {
nuclear@2 85 key_list = key_tail = node;
nuclear@2 86 }
nuclear@2 87 }
nuclear@2 88
nuclear@0 89 glutPostRedisplay();
nuclear@0 90 }
nuclear@0 91
nuclear@0 92 void imtk_inp_mouse(int bn, int state)
nuclear@0 93 {
nuclear@0 94 if(state == IMTK_DOWN) {
nuclear@0 95 mouse_bnmask |= 1 << bn;
nuclear@0 96 } else {
nuclear@0 97 mouse_bnmask &= ~(1 << bn);
nuclear@0 98 }
nuclear@0 99 glutPostRedisplay();
nuclear@0 100 }
nuclear@0 101
nuclear@0 102 void imtk_inp_motion(int x, int y)
nuclear@0 103 {
nuclear@0 104 mousex = x;
nuclear@0 105 mousey = y;
nuclear@0 106
nuclear@0 107 glutPostRedisplay();
nuclear@0 108 }
nuclear@0 109
nuclear@0 110 void imtk_inp_reshape(int x, int y)
nuclear@0 111 {
nuclear@0 112 scr_width = x;
nuclear@0 113 scr_height = y;
nuclear@0 114 }
nuclear@0 115
nuclear@0 116 void imtk_begin(void)
nuclear@0 117 {
nuclear@0 118 glMatrixMode(GL_PROJECTION);
nuclear@0 119 glPushMatrix();
nuclear@0 120 glLoadIdentity();
nuclear@0 121 glTranslatef(-1, 1, 0);
nuclear@0 122 glScalef(2.0 / scr_width, -2.0 / scr_height, 1.0);
nuclear@2 123
nuclear@2 124 glMatrixMode(GL_MODELVIEW);
nuclear@2 125 glPushMatrix();
nuclear@2 126 glLoadIdentity();
nuclear@2 127
nuclear@2 128 glPushAttrib(GL_ENABLE_BIT);
nuclear@2 129 glDisable(GL_DEPTH_TEST);
nuclear@2 130 glDisable(GL_CULL_FACE);
nuclear@2 131 glDisable(GL_LIGHTING);
nuclear@0 132 }
nuclear@0 133
nuclear@0 134 void imtk_end(void)
nuclear@0 135 {
nuclear@2 136 glPopAttrib();
nuclear@2 137
nuclear@0 138 glMatrixMode(GL_PROJECTION);
nuclear@0 139 glPopMatrix();
nuclear@2 140 glMatrixMode(GL_MODELVIEW);
nuclear@2 141 glPopMatrix();
nuclear@0 142 }
nuclear@0 143
nuclear@0 144 int imtk_button(int id, const char *label, int x, int y)
nuclear@0 145 {
nuclear@0 146 int w, h, res = 0;
nuclear@0 147 int over = 0;
nuclear@0 148
nuclear@0 149 assert(id >= 0);
nuclear@0 150
nuclear@0 151 calc_button_size(label, &w, &h);
nuclear@0 152
nuclear@0 153 if(hit_test(x, y, w, h)) {
nuclear@1 154 set_hot(id);
nuclear@0 155 over = 1;
nuclear@0 156 }
nuclear@0 157
nuclear@0 158 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
nuclear@0 159 if(over) {
nuclear@0 160 set_active(id);
nuclear@0 161 }
nuclear@0 162 } else { /* mouse button up */
nuclear@0 163 if(active == id) {
nuclear@0 164 set_active(-1);
nuclear@0 165 if(hot == id && over) {
nuclear@0 166 res = 1;
nuclear@0 167 }
nuclear@0 168 }
nuclear@0 169 }
nuclear@0 170
nuclear@1 171 draw_button(id, label, x, y);
nuclear@0 172 return res;
nuclear@0 173 }
nuclear@0 174
nuclear@1 175 int imtk_checkbox(int id, const char *label, int x, int y, int state)
nuclear@1 176 {
nuclear@1 177 int sz = CHECKBOX_SIZE;
nuclear@1 178 int over = 0;
nuclear@1 179
nuclear@1 180 assert(id >= 0);
nuclear@1 181
nuclear@1 182 if(hit_test(x, y, sz, sz)) {
nuclear@1 183 set_hot(id);
nuclear@1 184 over = 1;
nuclear@1 185 }
nuclear@1 186
nuclear@1 187 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
nuclear@1 188 if(over) {
nuclear@1 189 set_active(id);
nuclear@1 190 }
nuclear@1 191 } else { /* mouse button up */
nuclear@1 192 if(active == id) {
nuclear@1 193 set_active(-1);
nuclear@1 194 if(hot == id && over) {
nuclear@1 195 state = !state;
nuclear@1 196 }
nuclear@1 197 }
nuclear@1 198 }
nuclear@1 199
nuclear@1 200 draw_checkbox(id, label, x, y, state);
nuclear@1 201 return state;
nuclear@1 202 }
nuclear@1 203
nuclear@2 204 void imtk_textbox(int id, char *textbuf, size_t buf_sz, int x, int y)
nuclear@2 205 {
nuclear@2 206 int len, over = 0;
nuclear@2 207
nuclear@2 208 assert(id >= 0);
nuclear@2 209
nuclear@2 210 if(hit_test(x, y, TEXTBOX_SIZE, 20)) {
nuclear@2 211 set_hot(id);
nuclear@2 212 over = 1;
nuclear@2 213 }
nuclear@2 214
nuclear@2 215 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
nuclear@2 216 if(over) {
nuclear@2 217 set_active(id);
nuclear@2 218 }
nuclear@2 219 } else {
nuclear@2 220 if(active == id) {
nuclear@2 221 set_active(-1);
nuclear@2 222 if(hot == id && over) {
nuclear@2 223 input = id;
nuclear@2 224 }
nuclear@2 225 }
nuclear@2 226 }
nuclear@2 227
nuclear@2 228 if(input == id) {
nuclear@2 229 len = strlen(textbuf);
nuclear@2 230 while(key_list) {
nuclear@2 231 struct key_node *node = key_list;
nuclear@2 232 key_list = key_list->next;
nuclear@2 233
nuclear@2 234 if(isprint(node->key)) {
nuclear@2 235 if(len < buf_sz) {
nuclear@2 236 textbuf[len++] = (char)node->key;
nuclear@2 237 }
nuclear@2 238 } else {
nuclear@2 239 switch(node->key) {
nuclear@2 240 case '\b':
nuclear@2 241 if(len > 0) {
nuclear@2 242 textbuf[--len] = 0;
nuclear@2 243 }
nuclear@2 244 break;
nuclear@2 245
nuclear@2 246 default:
nuclear@2 247 break;
nuclear@2 248 }
nuclear@2 249 }
nuclear@2 250
nuclear@2 251 free(node);
nuclear@2 252 }
nuclear@2 253 key_list = key_tail = 0;
nuclear@2 254 }
nuclear@2 255
nuclear@2 256 draw_textbox(id, textbuf, x, y);
nuclear@2 257 }
nuclear@2 258
nuclear@3 259 float imtk_slider(int id, float pos, float min, float max, int x, int y)
nuclear@3 260 {
nuclear@3 261 int thumb_x, thumb_y, over = 0;
nuclear@3 262 float range = max - min;
nuclear@3 263
nuclear@3 264 assert(id >= 0);
nuclear@3 265
nuclear@3 266 pos = (pos - min) / range;
nuclear@3 267 if(pos < 0.0) pos = 0.0;
nuclear@3 268 if(pos > 1.0) pos = 1.0;
nuclear@3 269
nuclear@3 270 thumb_x = x + SLIDER_SIZE * pos - THUMB_WIDTH / 2;
nuclear@3 271 thumb_y = y - THUMB_HEIGHT / 2;
nuclear@3 272
nuclear@3 273 if(hit_test(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT)) {
nuclear@3 274 set_hot(id);
nuclear@3 275 over = 1;
nuclear@3 276 }
nuclear@3 277
nuclear@3 278 if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
nuclear@3 279 if(over && hot == id) {
nuclear@3 280 if(active != id) {
nuclear@3 281 prevx = mousex;
nuclear@3 282 }
nuclear@3 283 set_active(id);
nuclear@3 284 }
nuclear@3 285 } else {
nuclear@3 286 if(active == id) {
nuclear@3 287 set_active(-1);
nuclear@3 288 }
nuclear@3 289 }
nuclear@3 290
nuclear@3 291 if(active == id) {
nuclear@3 292 float dx = (float)(mousex - prevx) / (float)SLIDER_SIZE;
nuclear@3 293 pos += dx;
nuclear@3 294 prevx = mousex;
nuclear@3 295
nuclear@3 296 if(pos < 0.0) pos = 0.0;
nuclear@3 297 if(pos > 1.0) pos = 1.0;
nuclear@3 298 }
nuclear@3 299
nuclear@3 300 draw_slider(id, pos, min, max, x, y);
nuclear@3 301 return pos * range + min;
nuclear@3 302 }
nuclear@3 303
nuclear@3 304 void imtk_progress(int id, float pos, int x, int y)
nuclear@3 305 {
nuclear@3 306 draw_progress(id, pos, x, y);
nuclear@3 307 }
nuclear@3 308
nuclear@4 309 int imtk_listbox(int id, const char *list, int sel, int x, int y)
nuclear@4 310 {
nuclear@4 311 int i;
nuclear@4 312 assert(id >= 0);
nuclear@4 313
nuclear@4 314 if(!list) {
nuclear@4 315 return -1;
nuclear@4 316 }
nuclear@4 317
nuclear@4 318 if(id & 1) {
nuclear@4 319 id++;
nuclear@4 320 }
nuclear@4 321
nuclear@4 322 for(i=0; *list; i++) {
nuclear@4 323 if(imtk_button(id + i * 2 + 1, list, x, y + i * 20)) {
nuclear@4 324 sel = i;
nuclear@4 325 }
nuclear@4 326 list += strlen(list) + 1;
nuclear@4 327 }
nuclear@4 328 return sel;
nuclear@4 329 }
nuclear@4 330
nuclear@4 331 int imtk_combobox(int id, char *textbuf, size_t buf_sz, const char *list, int sel, int x, int y)
nuclear@4 332 {
nuclear@4 333 imtk_textbox(id + 1, textbuf, buf_sz, x, y);
nuclear@4 334 imtk_button(id + 3, "V", x + TEXTBOX_SIZE, y);
nuclear@4 335
nuclear@4 336 if(prev_active == id + 3) {
nuclear@4 337 sel = imtk_listbox(id + 5, list, sel, x, y + 20);
nuclear@4 338 }
nuclear@4 339 return sel;
nuclear@4 340 }
nuclear@4 341
nuclear@4 342 char *imtk_create_list(const char *first, ...)
nuclear@4 343 {
nuclear@4 344 int sz;
nuclear@4 345 char *buf, *item;
nuclear@4 346 va_list ap;
nuclear@4 347
nuclear@4 348 if(!first) {
nuclear@4 349 return 0;
nuclear@4 350 }
nuclear@4 351
nuclear@4 352 sz = strlen(first) + 2;
nuclear@4 353 if(!(buf = malloc(sz))) {
nuclear@4 354 return 0;
nuclear@4 355 }
nuclear@4 356 memcpy(buf, first, sz - 2);
nuclear@4 357 buf[sz - 1] = buf[sz - 2] = 0;
nuclear@4 358
nuclear@4 359 va_start(ap, first);
nuclear@4 360 while((item = va_arg(ap, char*))) {
nuclear@4 361 int len = strlen(item);
nuclear@4 362 char *tmp = realloc(buf, sz + len + 1);
nuclear@4 363 if(!tmp) {
nuclear@4 364 free(buf);
nuclear@4 365 return 0;
nuclear@4 366 }
nuclear@4 367 buf = tmp;
nuclear@4 368
nuclear@4 369 memcpy(buf + sz - 1, item, len);
nuclear@4 370 sz += len + 1;
nuclear@4 371 buf[sz - 1] = buf[sz - 2] = 0;
nuclear@4 372 }
nuclear@4 373 va_end(ap);
nuclear@4 374
nuclear@4 375 return buf;
nuclear@4 376 }
nuclear@4 377
nuclear@4 378 void imtk_free_list(char *list)
nuclear@4 379 {
nuclear@4 380 free(list);
nuclear@4 381 }
nuclear@4 382
nuclear@0 383 static void set_active(int id)
nuclear@0 384 {
nuclear@3 385 if(id == -1 || hot == id) {
nuclear@4 386 prev_active = active;
nuclear@3 387 active = id;
nuclear@3 388 }
nuclear@0 389 }
nuclear@0 390
nuclear@0 391 static int set_hot(int id)
nuclear@0 392 {
nuclear@0 393 if(active == -1) {
nuclear@0 394 hot = id;
nuclear@0 395 return 1;
nuclear@0 396 }
nuclear@0 397 return 0;
nuclear@0 398 }
nuclear@0 399
nuclear@0 400 static int hit_test(int x, int y, int w, int h)
nuclear@0 401 {
nuclear@0 402 return mousex >= x && mousex < (x + w) &&
nuclear@0 403 mousey >= y && mousey < (y + h);
nuclear@0 404 }
nuclear@0 405
nuclear@1 406 static void draw_button(int id, const char *label, int x, int y)
nuclear@0 407 {
nuclear@0 408 int width, height;
nuclear@0 409
nuclear@0 410 calc_button_size(label, &width, &height);
nuclear@0 411
nuclear@0 412 glBegin(GL_QUADS);
nuclear@1 413 if(hit_test(x, y, width, height)) {
nuclear@1 414 glColor3fv(colors[IMTK_FOCUS_COLOR]);
nuclear@0 415 } else {
nuclear@1 416 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@0 417 }
nuclear@0 418 glVertex2f(x, y);
nuclear@0 419 glVertex2f(x + width, y);
nuclear@0 420 glVertex2f(x + width, y + height);
nuclear@0 421 glVertex2f(x, y + height);
nuclear@0 422 glEnd();
nuclear@0 423
nuclear@1 424 draw_frame(x, y, width, height, active == id ? FRAME_INSET : FRAME_OUTSET);
nuclear@1 425
nuclear@1 426 glColor3fv(colors[IMTK_TEXT_COLOR]);
nuclear@0 427 draw_string(x + 20, y + 15, label);
nuclear@0 428 }
nuclear@0 429
nuclear@0 430 static void calc_button_size(const char *label, int *wret, int *hret)
nuclear@0 431 {
nuclear@0 432 int strsz = string_size(label);
nuclear@0 433 if(wret) *wret = strsz + 40;
nuclear@0 434 if(hret) *hret = 20;
nuclear@0 435 }
nuclear@0 436
nuclear@1 437 static void draw_checkbox(int id, const char *label, int x, int y, int state)
nuclear@1 438 {
nuclear@1 439 static const int sz = CHECKBOX_SIZE;
nuclear@1 440
nuclear@1 441 if(hit_test(x, y, sz, sz)) {
nuclear@1 442 glColor3fv(colors[IMTK_FOCUS_COLOR]);
nuclear@1 443 } else {
nuclear@1 444 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@1 445 }
nuclear@1 446
nuclear@1 447 glBegin(GL_QUADS);
nuclear@1 448 glVertex2f(x, y);
nuclear@1 449 glVertex2f(x + sz, y);
nuclear@1 450 glVertex2f(x + sz, y + sz);
nuclear@1 451 glVertex2f(x, y + sz);
nuclear@1 452 glEnd();
nuclear@1 453
nuclear@1 454 draw_frame(x, y, sz, sz, FRAME_INSET);
nuclear@1 455
nuclear@1 456 glColor3fv(colors[IMTK_TEXT_COLOR]);
nuclear@1 457 if(state) {
nuclear@1 458 glPushAttrib(GL_LINE_BIT);
nuclear@1 459 glLineWidth(2);
nuclear@1 460
nuclear@1 461 glBegin(GL_LINES);
nuclear@1 462 glVertex2f(x + 2, y + 2);
nuclear@1 463 glVertex2f(x + sz - 2, y + sz - 2);
nuclear@1 464 glVertex2f(x + sz - 2, y + 2);
nuclear@1 465 glVertex2f(x + 2, y + sz - 2);
nuclear@1 466 glEnd();
nuclear@1 467
nuclear@1 468 glPopAttrib();
nuclear@1 469 }
nuclear@1 470
nuclear@1 471 draw_string(x + sz + 5, y + sz - 2, label);
nuclear@1 472 }
nuclear@1 473
nuclear@2 474 static void draw_textbox(int id, const char *text, int x, int y)
nuclear@2 475 {
nuclear@2 476 int strsz = string_size(text);
nuclear@2 477
nuclear@2 478 if(hit_test(x, y, TEXTBOX_SIZE, 20)) {
nuclear@2 479 glColor3fv(colors[IMTK_FOCUS_COLOR]);
nuclear@2 480 } else {
nuclear@2 481 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@2 482 }
nuclear@2 483
nuclear@2 484 glBegin(GL_QUADS);
nuclear@2 485 glVertex2f(x, y);
nuclear@2 486 glVertex2f(x + TEXTBOX_SIZE, y);
nuclear@2 487 glVertex2f(x + TEXTBOX_SIZE, y + 20);
nuclear@2 488 glVertex2f(x, y + 20);
nuclear@2 489 glEnd();
nuclear@2 490
nuclear@2 491 glColor3fv(colors[IMTK_TEXT_COLOR]);
nuclear@2 492
nuclear@2 493 if(input == id) {
nuclear@2 494 glBegin(GL_LINES);
nuclear@2 495 glVertex2f(x + strsz + 2, y + 2);
nuclear@2 496 glVertex2f(x + strsz + 2, y + 18);
nuclear@2 497 glEnd();
nuclear@2 498 }
nuclear@2 499
nuclear@2 500 draw_string(x + 2, y + 15, text);
nuclear@2 501
nuclear@2 502 draw_frame(x, y, TEXTBOX_SIZE, 20, FRAME_INSET);
nuclear@2 503 }
nuclear@2 504
nuclear@3 505 static void draw_slider(int id, float pos, float min, float max, int x, int y)
nuclear@3 506 {
nuclear@3 507 float range = max - min;
nuclear@3 508 int thumb_x, thumb_y;
nuclear@3 509 char buf[32];
nuclear@3 510
nuclear@3 511 thumb_x = x + SLIDER_SIZE * pos - THUMB_WIDTH / 2;
nuclear@3 512 thumb_y = y - THUMB_HEIGHT / 2;
nuclear@3 513
nuclear@3 514 /* draw trough */
nuclear@3 515 glBegin(GL_QUADS);
nuclear@3 516 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@3 517 glVertex2f(x, y - 2);
nuclear@3 518 glVertex2f(x + SLIDER_SIZE, y - 2);
nuclear@3 519 glVertex2f(x + SLIDER_SIZE, y + 2);
nuclear@3 520 glVertex2f(x, y + 2);
nuclear@3 521 glEnd();
nuclear@3 522 draw_frame(x, y - 2, SLIDER_SIZE, 4, FRAME_INSET);
nuclear@3 523
nuclear@3 524 if(hit_test(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT)) {
nuclear@3 525 glColor3fv(colors[IMTK_FOCUS_COLOR]);
nuclear@3 526 } else {
nuclear@3 527 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@3 528 }
nuclear@3 529
nuclear@3 530 /* draw handle */
nuclear@3 531 glBegin(GL_QUADS);
nuclear@3 532 glVertex2f(thumb_x, thumb_y);
nuclear@3 533 glVertex2f(thumb_x + THUMB_WIDTH, thumb_y);
nuclear@3 534 glVertex2f(thumb_x + THUMB_WIDTH, thumb_y + THUMB_HEIGHT);
nuclear@3 535 glVertex2f(thumb_x, thumb_y + THUMB_HEIGHT);
nuclear@3 536 glEnd();
nuclear@3 537 draw_frame(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT, FRAME_OUTSET);
nuclear@3 538
nuclear@3 539 /* draw display */
nuclear@3 540 sprintf(buf, "%.3f", pos * range + min);
nuclear@3 541 glColor3fv(colors[IMTK_TEXT_COLOR]);
nuclear@3 542 draw_string(x + SLIDER_SIZE + THUMB_WIDTH / 2 + 2, y + 4, buf);
nuclear@3 543 }
nuclear@3 544
nuclear@3 545 static void draw_progress(int id, float pos, int x, int y)
nuclear@3 546 {
nuclear@3 547 int bar_size = SLIDER_SIZE * pos;
nuclear@3 548
nuclear@3 549 if(pos < 0.0) pos = 0.0;
nuclear@3 550 if(pos > 1.0) pos = 1.0;
nuclear@3 551
nuclear@3 552 /* through */
nuclear@3 553 glBegin(GL_QUADS);
nuclear@3 554 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@3 555 glVertex2f(x - 1, y - 1);
nuclear@3 556 glVertex2f(x + SLIDER_SIZE + 1, y - 1);
nuclear@3 557 glVertex2f(x + SLIDER_SIZE + 1, y + 17);
nuclear@3 558 glVertex2f(x - 1, y + 17);
nuclear@3 559 glEnd();
nuclear@3 560 draw_frame(x - 1, y - 1, SLIDER_SIZE + 2, 17, FRAME_INSET);
nuclear@3 561
nuclear@3 562 if(pos > 0.0) {
nuclear@3 563 /* bar */
nuclear@3 564 glBegin(GL_QUADS);
nuclear@3 565 glColor3fv(colors[IMTK_BASE_COLOR]);
nuclear@3 566 glVertex2f(x, y);
nuclear@3 567 glVertex2f(x + bar_size, y);
nuclear@3 568 glVertex2f(x + bar_size, y + 15);
nuclear@3 569 glVertex2f(x, y + 15);
nuclear@3 570 glEnd();
nuclear@3 571 draw_frame(x, y, bar_size, 15, FRAME_OUTSET);
nuclear@3 572 }
nuclear@3 573 }
nuclear@3 574
nuclear@0 575 static void draw_string(int x, int y, const char *str)
nuclear@0 576 {
nuclear@0 577 glRasterPos2i(x, y);
nuclear@0 578 while(*str) {
nuclear@1 579 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *str++);
nuclear@0 580 }
nuclear@0 581 }
nuclear@0 582
nuclear@0 583 static int string_size(const char *str)
nuclear@0 584 {
nuclear@1 585 return glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)str);
nuclear@0 586 }
nuclear@1 587
nuclear@1 588 static void draw_frame(int x, int y, int w, int h, int style)
nuclear@1 589 {
nuclear@1 590 float tcol[3], bcol[3];
nuclear@1 591
nuclear@1 592 switch(style) {
nuclear@1 593 case FRAME_INSET:
nuclear@1 594 memcpy(tcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof tcol);
nuclear@1 595 memcpy(bcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof bcol);
nuclear@1 596 break;
nuclear@1 597
nuclear@1 598 case FRAME_OUTSET:
nuclear@1 599 default:
nuclear@1 600 memcpy(tcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof tcol);
nuclear@1 601 memcpy(bcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof bcol);
nuclear@1 602 }
nuclear@1 603
nuclear@1 604 glBegin(GL_LINES);
nuclear@1 605 glColor3fv(tcol);
nuclear@1 606 glVertex2f(x, y + h);
nuclear@1 607 glVertex2f(x, y);
nuclear@1 608 glVertex2f(x, y);
nuclear@1 609 glVertex2f(x + w, y);
nuclear@1 610 glColor3fv(bcol);
nuclear@1 611 glVertex2f(x + w, y);
nuclear@1 612 glVertex2f(x + w, y + h);
nuclear@1 613 glVertex2f(x + w, y + h);
nuclear@1 614 glVertex2f(x, y + h);
nuclear@1 615 glEnd();
nuclear@1 616 }