1 /***************************************************************************
2                              guibutton.cpp
3                              -------------------
4     created              : Fri Aug 13 22:18:21 CEST 1999
5     copyright            : (C) 1999-2013 by Eric Espie, Bernhard Wymann
6     email                : torcs@free.fr
7     version              : $Id: guibutton.cpp,v 1.3.2.6 2013/08/28 13:07:33 berniw Exp $
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *   This program is free software; you can redistribute it and/or modify  *
13  *   it under the terms of the GNU General Public License as published by  *
14  *   the Free Software Foundation; either version 2 of the License, or     *
15  *   (at your option) any later version.                                   *
16  *                                                                         *
17  ***************************************************************************/
18 
19 
20 /** @file
21     		GUI Buttons Management.
22     @author	<a href=mailto:torcs@free.fr>Eric Espie</a>
23     @version	$Id: guibutton.cpp,v 1.3.2.6 2013/08/28 13:07:33 berniw Exp $
24     @ingroup	gui
25 */
26 
27 #include <stdlib.h>
28 #ifdef WIN32
29 #include <windows.h>
30 #endif
31 #include <tgfclient.h>
32 #include "gui.h"
33 #include "guifont.h"
34 
35 void
gfuiButtonInit(void)36 gfuiButtonInit(void)
37 {
38 }
39 
40 /** Add a graphical button to a screen.
41     @ingroup	gui
42     @param	scr		Screen
43     @param	disabled	filename of the image when the button is disabled
44     @param	enabled		filename of the image when the button is enabled
45     @param	focused		filename of the image when the button is focused
46     @param	pushed		filename of the image when the button is pushed
47     @param	x		X position on screen
48     @param	y		Y position on screen (0 = bottom)
49     @param	align		Button alignment
50     @param	mouse		Mouse behavior:
51     				<br>GFUI_MOUSE_UP Action performed when the mouse right button is released
52 				<br>GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed
53     @param	userDataOnPush	Parameter to the Push callback
54     @param	onPush		Push callback function
55     @param	userDataOnFocus	Parameter to the Focus (and lost) callback
56     @param	onFocus		Focus callback function
57     @param	onFocusLost	Focus Lost callback function
58     @return	Button Id
59 		<br>-1 Error
60  */
61 int
GfuiGrButtonCreate(void * scr,const char * disabled,const char * enabled,const char * focused,const char * pushed,int x,int y,int align,int mouse,void * userDataOnPush,tfuiCallback onPush,void * userDataOnFocus,tfuiCallback onFocus,tfuiCallback onFocusLost)62 GfuiGrButtonCreate(void *scr, const char *disabled, const char *enabled, const char *focused, const char *pushed,
63 		   int x, int y, int align, int mouse,
64 		   void *userDataOnPush, tfuiCallback onPush,
65 		   void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost)
66 {
67     tGfuiGrButton	*button;
68     tGfuiObject		*object;
69     tGfuiScreen		*screen = (tGfuiScreen*)scr;
70     int			width, height;
71 
72     object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject));
73     object->widget = GFUI_GRBUTTON;
74     object->focusMode = GFUI_FOCUS_MOUSE_MOVE;
75     object->id = screen->curId++;
76     object->visible = 1;
77 
78     button = &(object->u.grbutton);
79     button->state = GFUI_BTN_RELEASED;
80     button->userDataOnPush = userDataOnPush;
81     button->onPush = onPush;
82     button->userDataOnFocus = userDataOnFocus;
83     button->onFocus = onFocus;
84     button->onFocusLost = onFocusLost;
85     button->mouseBehaviour = mouse;
86 
87     button->disabled = GfImgReadPng(disabled, &width, &height, 1.0);
88     button->enabled = GfImgReadPng(enabled, &width, &height, 1.0);
89     button->focused = GfImgReadPng(focused, &width, &height, 1.0);
90     button->pushed = GfImgReadPng(pushed, &width, &height, 1.0);
91 
92     switch (align) {
93     case GFUI_ALIGN_HR_VB:
94 	object->xmin = x - width;
95 	object->xmax = x;
96 	object->ymin = y;
97 	object->ymax = y + height;
98 	break;
99     case GFUI_ALIGN_HR_VC:
100 	object->xmin = x - width;
101 	object->xmax = x;
102 	object->ymin = y - height / 2;
103 	object->ymax = y + height / 2;
104 	break;
105     case GFUI_ALIGN_HR_VT:
106 	object->xmin = x - width;
107 	object->xmax = x;
108 	object->ymin = y - height;
109 	object->ymax = y;
110 	break;
111     case GFUI_ALIGN_HC_VB:
112 	object->xmin = x - width / 2;
113 	object->xmax = x + width / 2;
114 	object->ymin = y;
115 	object->ymax = y + height;
116 	break;
117     case GFUI_ALIGN_HC_VC:
118 	object->xmin = x - width / 2;
119 	object->xmax = x + width / 2;
120 	object->ymin = y - height / 2;
121 	object->ymax = y + height / 2;
122 	break;
123     case GFUI_ALIGN_HC_VT:
124 	object->xmin = x - width / 2;
125 	object->xmax = x + width / 2;
126 	object->ymin = y - height;
127 	object->ymax = y;
128 	break;
129     case GFUI_ALIGN_HL_VB:
130 	object->xmin = x;
131 	object->xmax = x + width;
132 	object->ymin = y;
133 	object->ymax = y + height;
134 	break;
135     case GFUI_ALIGN_HL_VC:
136 	object->xmin = x;
137 	object->xmax = x + width;
138 	object->ymin = y - height / 2;
139 	object->ymax = y + height / 2;
140 	break;
141     case GFUI_ALIGN_HL_VT:
142 	object->xmin = x;
143 	object->xmax = x + width;
144 	object->ymin = y - height;
145 	object->ymax = y;
146 	break;
147     default:
148 	break;
149     }
150 
151     button->width = width;
152     button->height = height;
153 
154     gfuiAddObject(screen, object);
155     return object->id;
156 }
157 
158 /** Add a state button to a screen.
159     @ingroup	gui
160     @param	scr		Screen
161     @param	text		Button label
162     @param	font		Font id
163     @param	x		X position on screen
164     @param	y		Y position on screen (0 = bottom)
165     @param	width		width of the button (0 = text size)
166     @param	align		Button alignment:
167     			<br>GFUI_ALIGN_HR_VB	horizontal right, vertical bottom
168     			<br>GFUI_ALIGN_HR_VC	horizontal right, vertical center
169     			<br>GFUI_ALIGN_HR_VT	horizontal right, vertical top
170     			<br>GFUI_ALIGN_HC_VB	horizontal center, vertical bottom
171     			<br>GFUI_ALIGN_HC_VC	horizontal center, vertical center
172     			<br>GFUI_ALIGN_HC_VT	horizontal center, vertical top
173     			<br>GFUI_ALIGN_HL_VB	horizontal left, vertical bottom
174     			<br>GFUI_ALIGN_HL_VC	horizontal left, vertical center
175     			<br>GFUI_ALIGN_HL_VT	horizontal left, vertical top
176     @param	mouse		Mouse behavior:
177     				<br>GFUI_MOUSE_UP Action performed when the mouse right button is released
178 				<br>GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed
179     @param	userDataOnPush	Parameter to the Push callback
180     @param	onPush		Push callback function
181     @param	userDataOnFocus	Parameter to the Focus (and lost) callback
182     @param	onFocus		Focus callback function
183     @param	onFocusLost	Focus Lost callback function
184     @return	Button Id
185 		<br>-1 Error
186  */
187 int
GfuiButtonStateCreate(void * scr,const char * text,int font,int x,int y,int width,int align,int mouse,void * userDataOnPush,tfuiCallback onPush,void * userDataOnFocus,tfuiCallback onFocus,tfuiCallback onFocusLost)188 GfuiButtonStateCreate(void *scr, const char *text, int font, int x, int y, int width, int align, int mouse,
189 		      void *userDataOnPush, tfuiCallback onPush,
190 		      void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost)
191 {
192 	int id;
193 	tGfuiButton	*button;
194 	tGfuiObject *curObject;
195 	tGfuiScreen	*screen = (tGfuiScreen*)scr;
196 
197 	id = GfuiButtonCreate(scr, text, font, x, y, width, align, mouse, userDataOnPush, onPush, userDataOnFocus,
198 				onFocus, onFocusLost);
199 
200 	curObject = screen->objects;
201 	if (curObject != NULL) {
202 		do {
203 			curObject = curObject->next;
204 			if (curObject->id == id) {
205 				if (curObject->widget == GFUI_BUTTON) {
206 					button = &(curObject->u.button);
207 					button->buttonType = GFUI_BTN_STATE;
208 				}
209 				return id;
210 			}
211 		} while (curObject != screen->objects);
212 	}
213 
214 	return id;
215 }
216 
217 
218 /** Add a button to a screen.
219     @ingroup	gui
220     @param	scr		Screen
221     @param	text		Button label
222     @param	font		Font id
223     @param	x		X position on screen
224     @param	y		Y position on screen (0 = bottom)
225     @param	width		width of the button (0 = text size)
226     @param	align		Button alignment:
227     			<br>GFUI_ALIGN_HR_VB	horizontal right, vertical bottom
228     			<br>GFUI_ALIGN_HR_VC	horizontal right, vertical center
229     			<br>GFUI_ALIGN_HR_VT	horizontal right, vertical top
230     			<br>GFUI_ALIGN_HC_VB	horizontal center, vertical bottom
231     			<br>GFUI_ALIGN_HC_VC	horizontal center, vertical center
232     			<br>GFUI_ALIGN_HC_VT	horizontal center, vertical top
233     			<br>GFUI_ALIGN_HL_VB	horizontal left, vertical bottom
234     			<br>GFUI_ALIGN_HL_VC	horizontal left, vertical center
235     			<br>GFUI_ALIGN_HL_VT	horizontal left, vertical top
236     @param	mouse		Mouse behavior:
237     				<br>GFUI_MOUSE_UP Action performed when the mouse right button is released
238 				<br>GFUI_MOUSE_DOWN Action performed when the mouse right button is pushed
239     @param	userDataOnPush	Parameter to the Push callback
240     @param	onPush		Push callback function
241     @param	userDataOnFocus	Parameter to the Focus (and lost) callback
242     @param	onFocus		Focus callback function
243     @param	onFocusLost	Focus Lost callback function
244     @return	Button Id
245 		<br>-1 Error
246  */
247 int
GfuiButtonCreate(void * scr,const char * text,int font,int x,int y,int width,int align,int mouse,void * userDataOnPush,tfuiCallback onPush,void * userDataOnFocus,tfuiCallback onFocus,tfuiCallback onFocusLost)248 GfuiButtonCreate(void *scr, const char *text, int font, int x, int y, int width, int align, int mouse,
249 		 void *userDataOnPush, tfuiCallback onPush,
250 		 void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost)
251 {
252 	tGfuiButton	*button;
253 	tGfuiLabel	*label;
254 	tGfuiObject	*object;
255 	tGfuiScreen	*screen = (tGfuiScreen*)scr;
256 
257 
258 	object = (tGfuiObject*)calloc(1, sizeof(tGfuiObject));
259 	object->widget = GFUI_BUTTON;
260 	object->focusMode = GFUI_FOCUS_MOUSE_MOVE;
261 	object->id = screen->curId++;
262 	object->visible = 1;
263 
264 	button = &(object->u.button);
265 	button->state = GFUI_BTN_RELEASED;
266 	button->userDataOnPush = userDataOnPush;
267 	button->onPush = onPush;
268 	button->userDataOnFocus = userDataOnFocus;
269 	button->onFocus = onFocus;
270 	button->onFocusLost = onFocusLost;
271 	button->mouseBehaviour = mouse;
272 	button->buttonType = GFUI_BTN_PUSH;
273 
274 	button->bgColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]);
275 	button->bgColor[1] = &(GfuiColor[GFUI_BGBTNENABLED][0]);
276 	button->bgColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]);
277 	button->bgFocusColor[0] = &(GfuiColor[GFUI_BGBTNDISABLED][0]);
278 	button->bgFocusColor[1] = &(GfuiColor[GFUI_BGBTNFOCUS][0]);
279 	button->bgFocusColor[2] = &(GfuiColor[GFUI_BGBTNCLICK][0]);
280 	button->fgColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]);
281 	button->fgColor[1] = &(GfuiColor[GFUI_BTNENABLED][0]);
282 	button->fgColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]);
283 	button->fgFocusColor[0] = &(GfuiColor[GFUI_BTNDISABLED][0]);
284 	button->fgFocusColor[1] = &(GfuiColor[GFUI_BTNFOCUS][0]);
285 	button->fgFocusColor[2] = &(GfuiColor[GFUI_BTNCLICK][0]);
286 
287 	label = &(button->label);
288 	label->text = (char*)calloc(1, 100);
289 	strncpy(label->text, text, 100);
290 	label->text[99] = '\0';
291 	label->font = gfuiFont[font];
292 	label->maxlen = 99;
293 	if (width == 0) {
294 		width = gfuiFont[font]->getWidth((const char *)text);
295 	}
296 
297 	label->align = align;
298 
299 	switch(align&0xF0) {
300 		case 0x00 /* LEFT */:
301 			label->x = object->xmin = x;
302 			label->y = y - 2 * gfuiFont[font]->getDescender();
303 			object->ymin = y;
304 			object->xmax = x + width;
305 			object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender();
306 			break;
307 		case 0x10 /* CENTER */:
308 			object->xmin = x - width / 2;
309 			label->x = x - gfuiFont[font]->getWidth((const char *)text) / 2;
310 			label->y = y - 2 * gfuiFont[font]->getDescender();
311 			object->ymin = y;
312 			object->xmax = x + width / 2;
313 			object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender();
314 			break;
315 		case 0x20 /* RIGHT */:
316 			label->x = object->xmin = x - width;
317 			label->y = y - 2 * gfuiFont[font]->getDescender();
318 			object->ymin = y;
319 			object->xmax = x;
320 			object->ymax = y + gfuiFont[font]->getHeight() - gfuiFont[font]->getDescender();
321 			break;
322 	}
323 #define HORIZ_MARGIN 10
324 	object->xmin -= HORIZ_MARGIN;
325 	object->xmax += HORIZ_MARGIN;
326 
327 	gfuiAddObject(screen, object);
328 	return object->id;
329 }
330 
331 
GfuiLeanButtonCreate(void * scr,const char * text,int font,int x,int y,int width,int align,int mouse,void * userDataOnPush,tfuiCallback onPush,void * userDataOnFocus,tfuiCallback onFocus,tfuiCallback onFocusLost)332 int GfuiLeanButtonCreate(void *scr, const char *text, int font, int x, int y, int width, int align, int mouse,
333 				 void *userDataOnPush, tfuiCallback onPush,
334 				 void *userDataOnFocus, tfuiCallback onFocus, tfuiCallback onFocusLost)
335 {
336 	int id = GfuiButtonCreate(scr, text, font, x, y, width, align, mouse,
337 		userDataOnPush, onPush, userDataOnFocus, onFocus, onFocusLost);
338 	tGfuiObject *o = gfuiGetObject(scr, id);
339 	if (o->widget == GFUI_BUTTON) {
340 		// Undo margins
341 		o->xmax -= HORIZ_MARGIN;
342 		o->xmin += HORIZ_MARGIN;
343 
344 		tGfuiButton	*button = &(o->u.button);
345 		button->bgColor[1] = &(GfuiColor[GFUI_BGBTNFOCUS][0]);
346 	}
347 	return id;
348 }
349 
350 /** Change the label of a button.
351     @ingroup	gui
352     @param	scr	Screen
353     @param	id	Button Id
354     @param	text	New label of the button
355  */
356 void
GfuiButtonSetText(void * scr,int id,const char * text)357 GfuiButtonSetText(void *scr, int id, const char *text)
358 {
359 	tGfuiObject *curObject;
360 	tGfuiScreen	*screen = (tGfuiScreen*)scr;
361 	int oldmin, oldmax;
362 
363 	curObject = screen->objects;
364 	if (curObject != NULL) {
365 		do {
366 			curObject = curObject->next;
367 			if (curObject->id == id) {
368 				if (curObject->widget == GFUI_BUTTON) {
369 					oldmax = curObject->xmax;
370 					oldmin = curObject->xmin;
371 					gfuiSetLabelText(curObject, &(curObject->u.button.label), text);
372 					curObject->xmax = oldmax;
373 					curObject->xmin = oldmin;
374 				}
375 				return;
376 			}
377 		} while (curObject != screen->objects);
378 	}
379 }
380 
381 /** Get the Id of the button focused in the current screen.
382     @ingroup	gui
383     @return	Button Id
384 		<br>-1 if no button or no screen or the focus is not on a button
385  */
386 int
GfuiButtonGetFocused(void)387 GfuiButtonGetFocused(void)
388 {
389     tGfuiObject *curObject;
390 
391     if (GfuiScreen != NULL) {
392 	curObject = GfuiScreen->objects;
393 	if (curObject != NULL) {
394 	    do {
395 		curObject = curObject->next;
396 		if (curObject->focus) {
397 		    if (curObject->widget == GFUI_BUTTON) {
398 			return curObject->id;
399 		    }
400 		    return -1;
401 		}
402 	    } while (curObject != GfuiScreen->objects);
403 	}
404     }
405     return -1;
406 }
407 
408 void
gfuiDrawButton(tGfuiObject * obj)409 gfuiDrawButton(tGfuiObject *obj)
410 {
411 	tGfuiLabel *label;
412 	tGfuiButton	*button;
413 	float *fgColor;
414 	float *bgColor;
415 
416 	button = &(obj->u.button);
417 	if (obj->state == GFUI_DISABLE) {
418 		button->state = GFUI_BTN_DISABLE;
419 	} else if (obj->state == GFUI_ENABLE && button->state == GFUI_BTN_DISABLE) {
420 		button->state = GFUI_BTN_RELEASED;
421 	}
422 
423 	if (obj->focus) {
424 		fgColor = button->fgFocusColor[button->state];
425 		bgColor = button->bgFocusColor[button->state];
426 	} else {
427 		fgColor = button->fgColor[button->state];
428 		bgColor = button->bgColor[button->state];
429 	}
430 	if (bgColor[3] != 0.0) {
431 		glColor4fv(bgColor);
432 		glBegin(GL_QUADS);
433 		glVertex2i(obj->xmin, obj->ymin);
434 		glVertex2i(obj->xmin, obj->ymax);
435 		glVertex2i(obj->xmax, obj->ymax);
436 		glVertex2i(obj->xmax, obj->ymin);
437 		glEnd();
438 		glColor4fv(fgColor);
439 		glBegin(GL_LINE_STRIP);
440 		glVertex2i(obj->xmin, obj->ymin);
441 		glVertex2i(obj->xmin, obj->ymax);
442 		glVertex2i(obj->xmax, obj->ymax);
443 		glVertex2i(obj->xmax, obj->ymin);
444 		glVertex2i(obj->xmin, obj->ymin);
445 		glEnd();
446 	}
447 	label = &(button->label);
448 	glColor4fv(fgColor);
449 	gfuiPrintString(label->x, label->y, label->font, label->text);
450 }
451 
452 void
gfuiDrawGrButton(tGfuiObject * obj)453 gfuiDrawGrButton(tGfuiObject *obj)
454 {
455     int sw, sh, vw, vh;
456     tGfuiGrButton	*button;
457     unsigned char	*img;
458 
459     button = &(obj->u.grbutton);
460     if (obj->state == GFUI_DISABLE) {
461 	img = button->disabled;
462     } else if (button->state == GFUI_BTN_PUSHED) {
463 	img = button->pushed;
464     } else if (obj->focus) {
465 	img = button->focused;
466     } else {
467 	img = button->enabled;
468     }
469     GfScrGetSize(&sw, &sh, &vw, &vh);
470     glRasterPos2i(obj->xmin, obj->ymin);
471     glPixelZoom((float)vw / (float)GfuiScreen->width, (float)vh / (float)GfuiScreen->height);
472     glDrawPixels(button->width, button->height, GL_RGBA, GL_UNSIGNED_BYTE, img);
473 }
474 
475 void
gfuiGrButtonAction(int action)476 gfuiGrButtonAction(int action)
477 {
478 	tGfuiObject	*object = GfuiScreen->hasFocus;
479 	if (object->state == GFUI_DISABLE) {
480 		return;
481 	}
482 
483 	tGfuiGrButton	*button;
484     button = &(GfuiScreen->hasFocus->u.grbutton);
485 
486     switch (button->buttonType) {
487     case GFUI_BTN_PUSH:
488 	if (action == 2) { /* enter key */
489 	    if (button->onPush != NULL) {
490 		button->onPush(button->userDataOnPush);
491 	    }
492 	} else if (action == 1) { /* mouse up */
493 	    if (button->state != GFUI_BTN_RELEASED) {
494 		button->state = GFUI_BTN_RELEASED;
495 		if (button->mouseBehaviour == GFUI_MOUSE_UP) {
496 		    if (button->onPush != NULL) {
497 			button->onPush(button->userDataOnPush);
498 		    }
499 		}
500 	    }
501 	} else { /* mouse down */
502 	    if (button->state != GFUI_BTN_PUSHED) {
503 		button->state = GFUI_BTN_PUSHED;
504 		if (button->mouseBehaviour == GFUI_MOUSE_DOWN) {
505 		    if (button->onPush != NULL) {
506 			button->onPush(button->userDataOnPush);
507 		    }
508 		}
509 	    }
510 	}
511 	break;
512 
513     case GFUI_BTN_STATE:
514 	if (action == 2) { /* enter key */
515 	    if (button->state == GFUI_BTN_RELEASED) {
516 		button->state = GFUI_BTN_PUSHED;
517 		if (button->onPush != NULL) {
518 		    button->onPush(button->userDataOnPush);
519 		}
520 	    } else {
521 		button->state = GFUI_BTN_RELEASED;
522 	    }
523 	} else if (action == 1) { /* mouse up */
524 	    if (button->mouseBehaviour == GFUI_MOUSE_UP) {
525 		if (button->state == GFUI_BTN_RELEASED) {
526 		    button->state = GFUI_BTN_PUSHED;
527 		    if (button->onPush != NULL) {
528 			button->onPush(button->userDataOnPush);
529 		    }
530 		} else {
531 		    button->state = GFUI_BTN_RELEASED;
532 		}
533 	    }
534 	} else { /* mouse down */
535 	    if (button->mouseBehaviour == GFUI_MOUSE_DOWN) {
536 		if (button->state == GFUI_BTN_RELEASED) {
537 		    button->state = GFUI_BTN_PUSHED;
538 		    if (button->onPush != NULL) {
539 			button->onPush(button->userDataOnPush);
540 		    }
541 		} else {
542 		    button->state = GFUI_BTN_RELEASED;
543 		}
544 	    }
545 	}
546 	break;
547     }
548 }
549 
550 void
gfuiButtonAction(int action)551 gfuiButtonAction(int action)
552 {
553 	tGfuiObject	*object = GfuiScreen->hasFocus;
554 	if (object->state == GFUI_DISABLE) {
555 		return;
556 	}
557 
558 	tGfuiButton	*button;
559     button = &(GfuiScreen->hasFocus->u.button);
560 
561     switch (button->buttonType) {
562     case GFUI_BTN_PUSH:
563 	if (action == 2) { /* enter key */
564 	    if (button->onPush != NULL) {
565 		button->onPush(button->userDataOnPush);
566 	    }
567 	} else if (action == 1) { /* mouse up */
568 	    button->state = GFUI_BTN_RELEASED;
569 	    if (button->mouseBehaviour == GFUI_MOUSE_UP) {
570 		if (button->onPush != NULL) {
571 		    button->onPush(button->userDataOnPush);
572 		}
573 	    }
574 	} else { /* mouse down */
575 	    button->state = GFUI_BTN_PUSHED;
576 	    if (button->mouseBehaviour == GFUI_MOUSE_DOWN) {
577 		if (button->onPush != NULL) {
578 		    button->onPush(button->userDataOnPush);
579 		}
580 	    }
581 	}
582 	break;
583 
584     case GFUI_BTN_STATE:
585 	if (action == 2) { /* enter key */
586 	    if (button->state == GFUI_BTN_RELEASED) {
587 		button->state = GFUI_BTN_PUSHED;
588 		if (button->onPush != NULL) {
589 		    button->onPush(button->userDataOnPush);
590 		}
591 	    } else {
592 		button->state = GFUI_BTN_RELEASED;
593 	    }
594 	} else if (action == 1) { /* mouse up */
595 	    if (button->mouseBehaviour == GFUI_MOUSE_UP) {
596 		if (button->state == GFUI_BTN_RELEASED) {
597 		    button->state = GFUI_BTN_PUSHED;
598 		    if (button->onPush != NULL) {
599 			button->onPush(button->userDataOnPush);
600 		    }
601 		} else {
602 		    button->state = GFUI_BTN_RELEASED;
603 		}
604 	    }
605 	} else { /* mouse down */
606 	    if (button->mouseBehaviour == GFUI_MOUSE_DOWN) {
607 		if (button->state == GFUI_BTN_RELEASED) {
608 		    button->state = GFUI_BTN_PUSHED;
609 		    if (button->onPush != NULL) {
610 			button->onPush(button->userDataOnPush);
611 		    }
612 		} else {
613 		    button->state = GFUI_BTN_RELEASED;
614 		}
615 	    }
616 	}
617 	break;
618     }
619 }
620 
621 void
gfuiReleaseButton(tGfuiObject * obj)622 gfuiReleaseButton(tGfuiObject *obj)
623 {
624     tGfuiButton	*button;
625     tGfuiLabel	*label;
626 
627     button = &(obj->u.button);
628     label = &(button->label);
629 
630 	freez(button->userDataOnFocus);
631     free(label->text);
632     free(obj);
633 }
634 
635 void
gfuiReleaseGrButton(tGfuiObject * obj)636 gfuiReleaseGrButton(tGfuiObject *obj)
637 {
638     tGfuiGrButton	*button;
639 
640     button = &(obj->u.grbutton);
641 
642     free(button->disabled);
643     free(button->enabled);
644     free(button->focused);
645     free(button->pushed);
646     free(obj);
647 }
648