# HG changeset patch # User John Tsiombikas # Date 1302780162 -10800 # Node ID 38609a9f75865b06dd58583b6014b5422cf8d499 # Parent 09b6e8a5dc14c3a8523b991cf4e2039b8be54fbc reorganizing ... diff -r 09b6e8a5dc14 -r 38609a9f7586 src/button.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/button.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,69 @@ +#include +#include "imtk.h" +#include "state.h" +#include "draw.h" + +static void calc_button_size(const char *label, int *wret, int *hret); +static void draw_button(int id, const char *label, int x, int y); + +int imtk_button(int id, const char *label, int x, int y) +{ + int w, h, res = 0; + int over = 0; + + assert(id >= 0); + + calc_button_size(label, &w, &h); + + if(imtk_hit_test(x, y, w, h)) { + imtk_set_hot(id); + over = 1; + } + + if(imtk_button_state(IMTK_LEFT_BUTTON)) { + if(over) { + imtk_set_active(id); + } + } else { /* mouse button up */ + if(imtk_is_active(id)) { + imtk_set_active(-1); + if(imtk_is_hot(id) && over) { + res = 1; + } + } + } + + draw_button(id, label, x, y); + return res; +} + +static void draw_button(int id, const char *label, int x, int y) +{ + int width, height; + + calc_button_size(label, &width, &height); + + glBegin(GL_QUADS); + if(imtk_hit_test(x, y, width, height)) { + glColor4fv(imtk_get_color(IMTK_FOCUS_COLOR)); + } else { + glColor4fv(imtk_get_color(IMTK_BASE_COLOR)); + } + glVertex2f(x, y); + glVertex2f(x + width, y); + glVertex2f(x + width, y + height); + glVertex2f(x, y + height); + glEnd(); + + imtk_draw_frame(x, y, width, height, imtk_is_active(id) ? FRAME_INSET : FRAME_OUTSET); + + glColor4fv(imtk_get_color(IMTK_TEXT_COLOR)); + imtk_draw_string(x + 20, y + 15, label); +} + +static void calc_button_size(const char *label, int *wret, int *hret) +{ + int strsz = imtk_string_size(label); + if(wret) *wret = strsz + 40; + if(hret) *hret = 20; +} diff -r 09b6e8a5dc14 -r 38609a9f7586 src/checkbox.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/checkbox.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,78 @@ +#include +#include "imtk.h" +#include "state.h" +#include "draw.h" + + +#define CHECKBOX_SIZE 14 + + +static void draw_checkbox(int id, const char *label, int x, int y, int state); + + +int imtk_checkbox(int id, const char *label, int x, int y, int state) +{ + int sz = CHECKBOX_SIZE; + int over = 0; + + assert(id >= 0); + + if(imtk_hit_test(x, y, sz, sz)) { + imtk_set_hot(id); + over = 1; + } + + if(imtk_button_state(IMTK_LEFT_BUTTON)) { + if(over) { + imtk_set_active(id); + } + } else { /* mouse button up */ + if(imtk_is_active(id)) { + imtk_set_active(-1); + if(imtk_is_hot(id) && over) { + state = !state; + } + } + } + + draw_checkbox(id, label, x, y, state); + return state; +} + +static void draw_checkbox(int id, const char *label, int x, int y, int state) +{ + static const int sz = CHECKBOX_SIZE; + + if(imtk_hit_test(x, y, sz, sz)) { + glColor4fv(imtk_get_color(IMTK_FOCUS_COLOR)); + } else { + glColor4fv(imtk_get_color(IMTK_BASE_COLOR)); + } + + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x + sz, y); + glVertex2f(x + sz, y + sz); + glVertex2f(x, y + sz); + glEnd(); + + imtk_draw_frame(x, y, sz, sz, FRAME_INSET); + + glColor4fv(imtk_get_color(IMTK_TEXT_COLOR)); + if(state) { + glPushAttrib(GL_LINE_BIT); + glLineWidth(2); + + glBegin(GL_LINES); + glVertex2f(x + 2, y + 2); + glVertex2f(x + sz - 2, y + sz - 2); + glVertex2f(x + sz - 2, y + 2); + glVertex2f(x + 2, y + sz - 2); + glEnd(); + + glPopAttrib(); + } + + imtk_draw_string(x + sz + 5, y + sz - 2, label); +} + diff -r 09b6e8a5dc14 -r 38609a9f7586 src/draw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/draw.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,72 @@ +#include +#include +#include "draw.h" +#include "imtk.h" + +/* default colors, can be changed with imtk_set_color */ +static float colors[][4] = { + {0.0, 0.0, 0.0, 1.0}, /* text color */ + {0.7, 0.7, 0.7, 1.0}, /* base color */ + {0.85, 0.85, 0.85, 1.0}, /* focus color */ + {1.0, 1.0, 1.0, 1.0}, /* lit bevel */ + {0.3, 0.3, 0.3, 1.0} /* shadowed bevel */ +}; + +void imtk_set_color(int col, float r, float g, float b, float a) +{ + assert(col >= 0 && col < sizeof colors / sizeof *colors); + + colors[col][0] = r; + colors[col][1] = g; + colors[col][2] = b; + colors[col][3] = a; +} + +float *imtk_get_color(int col) +{ + return colors[col]; +} + +void imtk_draw_frame(int x, int y, int w, int h, int style) +{ + float tcol[4], bcol[4]; + + switch(style) { + case FRAME_INSET: + memcpy(tcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof tcol); + memcpy(bcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof bcol); + break; + + case FRAME_OUTSET: + default: + memcpy(tcol, colors[IMTK_BEVEL_LIT_COLOR], sizeof tcol); + memcpy(bcol, colors[IMTK_BEVEL_SHAD_COLOR], sizeof bcol); + } + + glBegin(GL_LINES); + glColor4fv(tcol); + glVertex2f(x, y + h); + glVertex2f(x, y); + glVertex2f(x, y); + glVertex2f(x + w, y); + glColor4fv(bcol); + glVertex2f(x + w, y); + glVertex2f(x + w, y + h); + glVertex2f(x + w, y + h); + glVertex2f(x, y + h); + glEnd(); + +} + +void imtk_draw_string(int x, int y, const char *str) +{ + glRasterPos2i(x, y); + while(*str) { + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *str++); + } +} + +int imtk_string_size(const char *str) +{ + return glutBitmapLength(GLUT_BITMAP_HELVETICA_12, (const unsigned char*)str); +} diff -r 09b6e8a5dc14 -r 38609a9f7586 src/draw.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/draw.h Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,30 @@ +#ifndef DRAW_H_ +#define DRAW_H_ + +#ifndef __APPLE__ +#include +#else +#include +#endif + +enum { + IMTK_TEXT_COLOR, + IMTK_BASE_COLOR, + IMTK_FOCUS_COLOR, + IMTK_BEVEL_LIT_COLOR, + IMTK_BEVEL_SHAD_COLOR +}; + + +enum { + FRAME_OUTSET, + FRAME_INSET +}; + +void imtk_set_color(int col, float r, float g, float b, float a); +float *imtk_get_color(int col); +void imtk_draw_frame(int x, int y, int w, int h, int style); +void imtk_draw_string(int x, int y, const char *str); +int imtk_string_size(const char *str); + +#endif /* DRAW_H_ */ diff -r 09b6e8a5dc14 -r 38609a9f7586 src/slider.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/slider.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,105 @@ +#include +#include +#include "imtk.h" +#include "state.h" +#include "draw.h" + +#define SLIDER_SIZE 100 +#define THUMB_WIDTH 10 +#define THUMB_HEIGHT 20 + +static void draw_slider(int id, float pos, float min, float max, int x, int y); + +float imtk_slider(int id, float pos, float min, float max, int x, int y) +{ + int mousex, mousey, thumb_x, thumb_y, over = 0; + float range = max - min; + + assert(id >= 0); + + imtk_get_mouse(&mousex, &mousey); + + pos = (pos - min) / range; + if(pos < 0.0) pos = 0.0; + if(pos > 1.0) pos = 1.0; + + thumb_x = x + SLIDER_SIZE * pos - THUMB_WIDTH / 2; + thumb_y = y - THUMB_HEIGHT / 2; + + if(imtk_hit_test(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT)) { + imtk_set_hot(id); + over = 1; + } + + if(imtk_button_state(IMTK_LEFT_BUTTON)) { + if(over && imtk_is_hot(id)) { + if(!imtk_is_active(id)) { + imtk_set_prev_mouse(mousex, mousey); + } + imtk_set_active(id); + } + } else { + if(imtk_is_active(id)) { + imtk_set_active(-1); + } + } + + if(imtk_is_active(id)) { + int prevx; + float dx; + + imtk_get_prev_mouse(&prevx, 0); + + dx = (float)(mousex - prevx) / (float)SLIDER_SIZE; + pos += dx; + prevx = mousex; + + if(pos < 0.0) pos = 0.0; + if(pos > 1.0) pos = 1.0; + } + + draw_slider(id, pos, min, max, x, y); + return pos * range + min; +} + + +static void draw_slider(int id, float pos, float min, float max, int x, int y) +{ + float range = max - min; + int thumb_x, thumb_y; + char buf[32]; + + thumb_x = x + SLIDER_SIZE * pos - THUMB_WIDTH / 2; + thumb_y = y - THUMB_HEIGHT / 2; + + /* draw trough */ + glBegin(GL_QUADS); + glColor4fv(imtk_get_color(IMTK_BASE_COLOR)); + glVertex2f(x, y - 2); + glVertex2f(x + SLIDER_SIZE, y - 2); + glVertex2f(x + SLIDER_SIZE, y + 2); + glVertex2f(x, y + 2); + glEnd(); + imtk_draw_frame(x, y - 2, SLIDER_SIZE, 4, FRAME_INSET); + + if(imtk_hit_test(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT)) { + glColor4fv(imtk_get_color(IMTK_FOCUS_COLOR)); + } else { + glColor4fv(imtk_get_color(IMTK_BASE_COLOR)); + } + + /* draw handle */ + glBegin(GL_QUADS); + glVertex2f(thumb_x, thumb_y); + glVertex2f(thumb_x + THUMB_WIDTH, thumb_y); + glVertex2f(thumb_x + THUMB_WIDTH, thumb_y + THUMB_HEIGHT); + glVertex2f(thumb_x, thumb_y + THUMB_HEIGHT); + glEnd(); + imtk_draw_frame(thumb_x, thumb_y, THUMB_WIDTH, THUMB_HEIGHT, FRAME_OUTSET); + + /* draw display */ + sprintf(buf, "%.3f", pos * range + min); + glColor4fv(imtk_get_color(IMTK_TEXT_COLOR)); + imtk_draw_string(x + SLIDER_SIZE + THUMB_WIDTH / 2 + 2, y + 4, buf); +} + diff -r 09b6e8a5dc14 -r 38609a9f7586 src/state.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/state.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,148 @@ +#include "state.h" +#include "imtk.h" + +struct key_node { + int key; + struct key_node *next; +}; + + +struct imtk_state st = { + 1, 1, /* scr_width/scr_height */ + 0, 0, 0, 0, 0, /* mousex/mousey, prevx, prevy, mouse_bnmask */ + -1, -1, -1, -1 /* active, hot, input, prev_active */ +}; + +static struct key_node *key_list, *key_tail; + + + +void imtk_inp_key(int key, int state) +{ + if(state == IMTK_DOWN) { + struct key_node *node; + + if(!(node = malloc(sizeof *node))) { + return; + } + node->key = key; + node->next = 0; + + if(key_list) { + key_tail->next = node; + key_tail = node; + } else { + key_list = key_tail = node; + } + } + + imtk_post_redisplay(); +} + +void imtk_inp_mouse(int bn, int state) +{ + if(state == IMTK_DOWN) { + st.mouse_bnmask |= 1 << bn; + } else { + st.mouse_bnmask &= ~(1 << bn); + } + imtk_post_redisplay(); +} + +void imtk_inp_motion(int x, int y) +{ + st.mousex = x; + st.mousey = y; + + imtk_post_redisplay(); +} + +void imtk_inp_reshape(int x, int y) +{ + st.scr_width = x; + st.scr_height = y; +} + + +void imtk_set_active(int id) +{ + if(id == -1 || st.hot == id) { + st.prev_active = st.active; + st.active = id; + } +} + +int imtk_is_active(int id) +{ + return st.active == id; +} + +int imtk_set_hot(int id) +{ + if(st.active == -1) { + st.hot = id; + return 1; + } + return 0; +} + +int imtk_is_hot(int id) +{ + return st.hot == id; +} + +void imtk_set_focus(int id) +{ + st.input = id; +} + +int imtk_has_focus(int id) +{ + return st.input == id; +} + +int imtk_hit_test(int x, int y, int w, int h) +{ + return st.mousex >= x && st.mousex < (x + w) && + st.mousey >= y && st.mousey < (y + h); +} + +void imtk_get_mouse(int *xptr, int *yptr) +{ + if(xptr) *xptr = st.mousex; + if(yptr) *yptr = st.mousey; +} + +void imtk_set_prev_mouse(int x, int y) +{ + st.prevx = x; + st.prevy = y; +} + +void imtk_get_prev_mouse(int *xptr, int *yptr) +{ + if(xptr) *xptr = st.prevx; + if(yptr) *yptr = st.prevy; +} + +int imtk_button_state(int bn) +{ + return st.mouse_bnmask & (1 << bn); +} + + +int imtk_get_key(void) +{ + int key = -1; + struct key_node *node = key_list; + + if(node) { + key = node->key; + key_list = node->next; + if(!key_list) { + key_tail = 0; + } + free(node); + } + return key; +} diff -r 09b6e8a5dc14 -r 38609a9f7586 src/state.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/state.h Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,26 @@ +#ifndef STATE_H_ +#define STATE_H_ + +struct imtk_state { + int scr_width, scr_height; + int mousex, mousey, prevx, prevy, mouse_bnmask; + int active, hot, input, prev_active; +}; + +void imtk_set_active(int id); +int imtk_is_active(int id); +int imtk_set_hot(int id); +int imtk_is_hot(int id); +void imtk_set_focus(int id); +int imtk_has_focus(int id); +int imtk_hit_test(int x, int y, int w, int h); + +void imtk_get_mouse(int *xptr, int *yptr); +void imtk_set_prev_mouse(int x, int y); +void imtk_get_prev_mouse(int *xptr, int *yptr); +int imtk_button_state(int bn); + +int imtk_get_key(void); + + +#endif /* STATE_H_ */ diff -r 09b6e8a5dc14 -r 38609a9f7586 src/textbox.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/textbox.c Thu Apr 14 14:22:42 2011 +0300 @@ -0,0 +1,95 @@ +#include +#include +#include +#include "imtk.h" +#include "state.h" +#include "draw.h" + +#define TEXTBOX_SIZE 100 + +static void draw_textbox(int id, const char *text, int x, int y); + + +void imtk_textbox(int id, char *textbuf, size_t buf_sz, int x, int y) +{ + int len, over = 0; + + assert(id >= 0); + + if(imtk_hit_test(x, y, TEXTBOX_SIZE, 20)) { + imtk_set_hot(id); + over = 1; + } + + if(imtk_button_state(IMTK_LEFT_BUTTON)) { + if(over) { + imtk_set_active(id); + } + } else { + if(imtk_is_active(id)) { + imtk_set_active(-1); + if(imtk_is_hot(id) && over) { + imtk_set_focus(id); + } + } + } + + if(imtk_has_focus(id)) { + int key; + len = strlen(textbuf); + + while((key = imtk_get_key()) != -1) { + if(isprint(key)) { + if(len < buf_sz) { + textbuf[len++] = (char)key; + } + } else { + switch(key) { + case '\b': + if(len > 0) { + textbuf[--len] = 0; + } + break; + + default: + break; + } + } + } + } + + draw_textbox(id, textbuf, x, y); +} + + +static void draw_textbox(int id, const char *text, int x, int y) +{ + int strsz = imtk_string_size(text); + + if(imtk_hit_test(x, y, TEXTBOX_SIZE, 20)) { + glColor4fv(imtk_get_color(IMTK_FOCUS_COLOR)); + } else { + glColor4fv(imtk_get_color(IMTK_BASE_COLOR)); + } + + glBegin(GL_QUADS); + glVertex2f(x, y); + glVertex2f(x + TEXTBOX_SIZE, y); + glVertex2f(x + TEXTBOX_SIZE, y + 20); + glVertex2f(x, y + 20); + glEnd(); + + glColor4fv(imtk_get_color(IMTK_TEXT_COLOR)); + + if(imtk_has_focus(id)) { + glBegin(GL_LINES); + glVertex2f(x + strsz + 2, y + 2); + glVertex2f(x + strsz + 2, y + 18); + glEnd(); + } + + imtk_draw_string(x + 2, y + 15, text); + + imtk_draw_frame(x, y, TEXTBOX_SIZE, 20, FRAME_INSET); +} +