glamtk

changeset 2:3d661dd17af3

- initial textbox implementation added - made the test program slightly more interesting
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 31 Dec 2010 01:54:53 +0200
parents dfbd12d1f566
children 038e5577d527
files src/imtk.c src/imtk.h test.c
diffstat 3 files changed, 210 insertions(+), 28 deletions(-) [+]
line diff
     1.1 --- a/src/imtk.c	Thu Dec 30 15:10:25 2010 +0200
     1.2 +++ b/src/imtk.c	Fri Dec 31 01:54:53 2010 +0200
     1.3 @@ -1,5 +1,6 @@
     1.4 -#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6  #include <string.h>
     1.7 +#include <ctype.h>
     1.8  #include <assert.h>
     1.9  #ifndef __APPLE__
    1.10  #include <GL/glut.h>
    1.11 @@ -9,12 +10,31 @@
    1.12  #include "imtk.h"
    1.13  
    1.14  #define CHECKBOX_SIZE	14
    1.15 +#define TEXTBOX_SIZE	100
    1.16  
    1.17  enum {
    1.18  	FRAME_OUTSET,
    1.19  	FRAME_INSET
    1.20  };
    1.21  
    1.22 +struct key_node {
    1.23 +	int key;
    1.24 +	struct key_node *next;
    1.25 +};
    1.26 +
    1.27 +static void set_active(int id);
    1.28 +static int set_hot(int id);
    1.29 +static int hit_test(int x, int y, int w, int h);
    1.30 +
    1.31 +static void draw_button(int id, const char *label, int x, int y);
    1.32 +static void calc_button_size(const char *label, int *wret, int *hret);
    1.33 +static void draw_checkbox(int id, const char *label, int x, int y, int state);
    1.34 +static void draw_textbox(int id, const char *text, int x, int y);
    1.35 +static void draw_string(int x, int y, const char *str);
    1.36 +static int string_size(const char *str);
    1.37 +static void draw_frame(int x, int y, int w, int h, int style);
    1.38 +
    1.39 +
    1.40  /* default colors, can be changed with imtk_set_color */
    1.41  static float colors[][4] = {
    1.42  	{0.0, 0.0, 0.0},	/* text color */
    1.43 @@ -26,18 +46,10 @@
    1.44  
    1.45  static int scr_width = 1, scr_height = 1;
    1.46  static int mousex, mousey, mouse_bnmask;
    1.47 -static int active = -1, hot = -1;
    1.48 +static int active = -1, hot = -1, input = -1;
    1.49  
    1.50 -static void set_active(int id);
    1.51 -static int set_hot(int id);
    1.52 -static int hit_test(int x, int y, int w, int h);
    1.53 +static struct key_node *key_list, *key_tail;
    1.54  
    1.55 -static void draw_button(int id, const char *label, int x, int y);
    1.56 -static void calc_button_size(const char *label, int *wret, int *hret);
    1.57 -static void draw_checkbox(int id, const char *label, int x, int y, int state);
    1.58 -static void draw_string(int x, int y, const char *str);
    1.59 -static int string_size(const char *str);
    1.60 -static void draw_frame(int x, int y, int w, int h, int style);
    1.61  
    1.62  void imtk_set_color(int col, float r, float g, float b)
    1.63  {
    1.64 @@ -50,6 +62,23 @@
    1.65  
    1.66  void imtk_inp_key(int key, int state)
    1.67  {
    1.68 +	if(state == IMTK_DOWN) {
    1.69 +		struct key_node *node;
    1.70 +
    1.71 +		if(!(node = malloc(sizeof *node))) {
    1.72 +			return;
    1.73 +		}
    1.74 +		node->key = key;
    1.75 +		node->next = 0;
    1.76 +
    1.77 +		if(key_list) {
    1.78 +			key_tail->next = node;
    1.79 +			key_tail = node;
    1.80 +		} else {
    1.81 +			key_list = key_tail = node;
    1.82 +		}
    1.83 +	}
    1.84 +
    1.85  	glutPostRedisplay();
    1.86  }
    1.87  
    1.88 @@ -84,12 +113,25 @@
    1.89  	glLoadIdentity();
    1.90  	glTranslatef(-1, 1, 0);
    1.91  	glScalef(2.0 / scr_width, -2.0 / scr_height, 1.0);
    1.92 +
    1.93 +	glMatrixMode(GL_MODELVIEW);
    1.94 +	glPushMatrix();
    1.95 +	glLoadIdentity();
    1.96 +
    1.97 +	glPushAttrib(GL_ENABLE_BIT);
    1.98 +	glDisable(GL_DEPTH_TEST);
    1.99 +	glDisable(GL_CULL_FACE);
   1.100 +	glDisable(GL_LIGHTING);
   1.101  }
   1.102  
   1.103  void imtk_end(void)
   1.104  {
   1.105 +	glPopAttrib();
   1.106 +
   1.107  	glMatrixMode(GL_PROJECTION);
   1.108  	glPopMatrix();
   1.109 +	glMatrixMode(GL_MODELVIEW);
   1.110 +	glPopMatrix();
   1.111  }
   1.112  
   1.113  int imtk_button(int id, const char *label, int x, int y)
   1.114 @@ -152,6 +194,61 @@
   1.115  	return state;
   1.116  }
   1.117  
   1.118 +void imtk_textbox(int id, char *textbuf, size_t buf_sz, int x, int y)
   1.119 +{
   1.120 +	int len, over = 0;
   1.121 +
   1.122 +	assert(id >= 0);
   1.123 +
   1.124 +	if(hit_test(x, y, TEXTBOX_SIZE, 20)) {
   1.125 +		set_hot(id);
   1.126 +		over = 1;
   1.127 +	}
   1.128 +
   1.129 +	if(mouse_bnmask & (1 << IMTK_LEFT_BUTTON)) {
   1.130 +		if(over) {
   1.131 +			set_active(id);
   1.132 +		}
   1.133 +	} else {
   1.134 +		if(active == id) {
   1.135 +			set_active(-1);
   1.136 +			if(hot == id && over) {
   1.137 +				input = id;
   1.138 +			}
   1.139 +		}
   1.140 +	}
   1.141 +
   1.142 +	if(input == id) {
   1.143 +		len = strlen(textbuf);
   1.144 +		while(key_list) {
   1.145 +			struct key_node *node = key_list;
   1.146 +			key_list = key_list->next;
   1.147 +
   1.148 +			if(isprint(node->key)) {
   1.149 +				if(len < buf_sz) {
   1.150 +					textbuf[len++] = (char)node->key;
   1.151 +				}
   1.152 +			} else {
   1.153 +				switch(node->key) {
   1.154 +				case '\b':
   1.155 +					if(len > 0) {
   1.156 +						textbuf[--len] = 0;
   1.157 +					}
   1.158 +					break;
   1.159 +
   1.160 +				default:
   1.161 +					break;
   1.162 +				}
   1.163 +			}
   1.164 +
   1.165 +			free(node);
   1.166 +		}
   1.167 +		key_list = key_tail = 0;
   1.168 +	}
   1.169 +
   1.170 +	draw_textbox(id, textbuf, x, y);
   1.171 +}
   1.172 +
   1.173  static void set_active(int id)
   1.174  {
   1.175  	active = id;
   1.176 @@ -240,6 +337,37 @@
   1.177  	draw_string(x + sz + 5, y + sz - 2, label);
   1.178  }
   1.179  
   1.180 +static void draw_textbox(int id, const char *text, int x, int y)
   1.181 +{
   1.182 +	int strsz = string_size(text);
   1.183 +
   1.184 +	if(hit_test(x, y, TEXTBOX_SIZE, 20)) {
   1.185 +		glColor3fv(colors[IMTK_FOCUS_COLOR]);
   1.186 +	} else {
   1.187 +		glColor3fv(colors[IMTK_BASE_COLOR]);
   1.188 +	}
   1.189 +
   1.190 +	glBegin(GL_QUADS);
   1.191 +	glVertex2f(x, y);
   1.192 +	glVertex2f(x + TEXTBOX_SIZE, y);
   1.193 +	glVertex2f(x + TEXTBOX_SIZE, y + 20);
   1.194 +	glVertex2f(x, y + 20);
   1.195 +	glEnd();
   1.196 +
   1.197 +	glColor3fv(colors[IMTK_TEXT_COLOR]);
   1.198 +
   1.199 +	if(input == id) {
   1.200 +		glBegin(GL_LINES);
   1.201 +		glVertex2f(x + strsz + 2, y + 2);
   1.202 +		glVertex2f(x + strsz + 2, y + 18);
   1.203 +		glEnd();
   1.204 +	}
   1.205 +
   1.206 +	draw_string(x + 2, y + 15, text);
   1.207 +
   1.208 +	draw_frame(x, y, TEXTBOX_SIZE, 20, FRAME_INSET);
   1.209 +}
   1.210 +
   1.211  static void draw_string(int x, int y, const char *str)
   1.212  {
   1.213  	glRasterPos2i(x, y);
     2.1 --- a/src/imtk.h	Thu Dec 30 15:10:25 2010 +0200
     2.2 +++ b/src/imtk.h	Fri Dec 31 01:54:53 2010 +0200
     2.3 @@ -33,7 +33,9 @@
     2.4  void imtk_begin(void);
     2.5  void imtk_end(void);
     2.6  
     2.7 +void imtk_window(int id, const char *title, int x, int y, int width, int height);
     2.8  int imtk_button(int id, const char *label, int x, int y);
     2.9  int imtk_checkbox(int id, const char *label, int x, int y, int state);
    2.10 +void imtk_textbox(int id, char *textbuf, size_t buf_sz, int x, int y);
    2.11  
    2.12  #endif	/* IMTK_H_ */
     3.1 --- a/test.c	Thu Dec 30 15:10:25 2010 +0200
     3.2 +++ b/test.c	Fri Dec 31 01:54:53 2010 +0200
     3.3 @@ -1,5 +1,6 @@
     3.4  #include <stdio.h>
     3.5  #include <stdlib.h>
     3.6 +#include <assert.h>
     3.7  #ifndef __APPLE__
     3.8  #include <GL/glut.h>
     3.9  #else
    3.10 @@ -17,9 +18,14 @@
    3.11  void mouse(int bn, int state, int x, int y);
    3.12  void motion(int x, int y);
    3.13  
    3.14 +int xsz, ysz;
    3.15  
    3.16  int main(int argc, char **argv)
    3.17  {
    3.18 +	float lpos[] = {-1, 1, 1, 0};
    3.19 +	float white[] = {1, 1, 1, 1};
    3.20 +	float color[] = {0.9, 0.8, 0.73, 1};
    3.21 +
    3.22  	glutInitWindowSize(800, 600);
    3.23  	glutInit(&argc, argv);
    3.24  	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    3.25 @@ -35,54 +41,100 @@
    3.26  	glutMotionFunc(motion);
    3.27  	glutPassiveMotionFunc(motion);
    3.28  
    3.29 +	glEnable(GL_DEPTH_TEST);
    3.30 +	glEnable(GL_CULL_FACE);
    3.31 +	glEnable(GL_LIGHTING);
    3.32 +	glEnable(GL_LIGHT0);
    3.33 +	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    3.34 +
    3.35 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
    3.36 +	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
    3.37 +	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0);
    3.38 +
    3.39  	glutMainLoop();
    3.40  	return 0;
    3.41  }
    3.42  
    3.43  void disp(void)
    3.44  {
    3.45 -	glClearColor(0.6, 0.6, 0.6, 0.0);
    3.46  	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    3.47  
    3.48 +	glViewport(200, 0, xsz - 200, ysz);
    3.49 +
    3.50 +	glMatrixMode(GL_PROJECTION);
    3.51 +	glLoadIdentity();
    3.52 +	gluPerspective(45.0, (float)(xsz - 200) / (float)ysz, 1.0, 1000.0);
    3.53 +
    3.54 +	glMatrixMode(GL_MODELVIEW);
    3.55 +	glLoadIdentity();
    3.56 +	glTranslatef(0, 0, -8);
    3.57 +	glRotatef(25, 1, 0, 0);
    3.58 +
    3.59 +	glFrontFace(GL_CW);
    3.60 +	glutSolidTeapot(1.0);
    3.61 +	glFrontFace(GL_CCW);
    3.62 +
    3.63 +
    3.64 +	glViewport(0, 0, 200, ysz);
    3.65 +	imtk_inp_reshape(200, ysz);
    3.66 +
    3.67  	gui();
    3.68  
    3.69  	glutSwapBuffers();
    3.70 +	assert(glGetError() == GL_NO_ERROR);
    3.71  }
    3.72  
    3.73  void gui(void)
    3.74  {
    3.75  	static int bnshow;
    3.76 +	static char textbuf[256];
    3.77 +	static char textbuf2[256];
    3.78  
    3.79  	imtk_begin();
    3.80  
    3.81 -	if(imtk_button(IMUID, "foobar", 100, 100)) {
    3.82 -		printf("clicked button 0\n");
    3.83 +	glBegin(GL_QUADS);
    3.84 +	glColor3f(0.6, 0.6, 0.6);
    3.85 +	glVertex2f(0, 0);
    3.86 +	glVertex2f(200, 0);
    3.87 +	glVertex2f(200, glutGet(GLUT_WINDOW_HEIGHT));
    3.88 +	glVertex2f(0, glutGet(GLUT_WINDOW_HEIGHT));
    3.89 +	glEnd();
    3.90 +
    3.91 +	if(imtk_button(IMUID, "red", 30, 50)) {
    3.92 +		float color[] = {1, 0.4, 0.3, 1};
    3.93 +		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
    3.94 +		glutPostRedisplay();
    3.95  	}
    3.96 -	if(imtk_button(IMUID, "xyzzy", 100, 200)) {
    3.97 -		printf("clicked button 1\n");
    3.98 -	}
    3.99 -	if(imtk_button(IMUID, "Quit", 100, 500)) {
   3.100 -		exit(0);
   3.101 +	if(imtk_button(IMUID, "blue", 30, 100)) {
   3.102 +		float color[] = {0.3, 0.4, 1, 1};
   3.103 +		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
   3.104 +		glutPostRedisplay();
   3.105  	}
   3.106  
   3.107 -	if((bnshow = imtk_checkbox(IMUID, "show hidden button", 100, 260, bnshow))) {
   3.108 -		if(imtk_button(IMUID, "I was hidden!", 130, 300)) {
   3.109 -			printf("you clicked the hidden button!\n");
   3.110 +	imtk_textbox(IMUID, textbuf, sizeof textbuf, 30, 200);
   3.111 +	imtk_textbox(IMUID, textbuf2, sizeof textbuf2, 30, 250);
   3.112 +
   3.113 +	if((bnshow = imtk_checkbox(IMUID, "show hidden button", 30, 300, bnshow))) {
   3.114 +		if(imtk_button(IMUID, "yellow", 50, 340)) {
   3.115 +			float color[] = {0.8, 0.75, 0.3, 1};
   3.116 +			glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
   3.117 +			glutPostRedisplay();
   3.118  		}
   3.119  	}
   3.120  
   3.121 +	if(imtk_button(IMUID, "Quit", 30, 500)) {
   3.122 +		exit(0);
   3.123 +	}
   3.124 +
   3.125  	imtk_end();
   3.126  }
   3.127  
   3.128  void reshape(int x, int y)
   3.129  {
   3.130 +	xsz = x;
   3.131 +	ysz = y;
   3.132 +
   3.133  	glViewport(0, 0, x, y);
   3.134 -	imtk_inp_reshape(x, y);
   3.135 -
   3.136 -	glMatrixMode(GL_PROJECTION);
   3.137 -	glLoadIdentity();
   3.138 -	glTranslatef(-1, -1, 0);
   3.139 -	glScalef(2.0 / x, 2.0 / y, 1.0);
   3.140  }
   3.141  
   3.142  void keyb(unsigned char key, int x, int y)