imtk

annotate 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
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 }