1 /***************************************************************************
2                                 guiobject.cpp
3                              -------------------
4     created              : Fri Aug 13 22:25:06 CEST 1999
5     copyright            : (C) 1999 by Eric Espie
6     email                : torcs@free.fr
7     version              : $Id: guiobject.cpp,v 1.3.2.3 2013/08/27 14:26:58 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 #ifdef WIN32
21 #include <windows.h>
22 #endif
23 #include <tgfclient.h>
24 #include "gui.h"
25 
26 void
gfuiObjectInit(void)27 gfuiObjectInit(void)
28 {
29 }
30 
31 void
gfuiPrintString(int x,int y,GfuiFontClass * font,const char * string)32 gfuiPrintString(int x, int y, GfuiFontClass *font, const char *string)
33 {
34     glEnable(GL_TEXTURE_2D);
35     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
36     glEnable(GL_ALPHA_TEST);
37     glAlphaFunc(GL_GREATER, 0.1) ;
38     font->output(x, y, string);
39     glDisable(GL_ALPHA_TEST);
40     glDisable(GL_TEXTURE_2D);
41 }
42 
GfuiPrintString(const char * text,float * fgColor,int font,int x,int y,int align)43 void GfuiPrintString(const char *text, float *fgColor, int font, int x, int y, int align)
44 {
45 	glEnable(GL_TEXTURE_2D);
46 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
47 	glEnable(GL_ALPHA_TEST);
48 	glAlphaFunc(GL_GREATER, 0.1) ;
49 	glColor4fv(fgColor);
50 	switch(align&0xF0) {
51 		case 0x00 /* LEFT */:
52 			gfuiFont[font]->output(x, y, text);
53 			break;
54 		case 0x10 /* CENTER */:
55 			gfuiFont[font]->output(x - gfuiFont[font]->getWidth(text) / 2, y, text);
56 			break;
57 		case 0x20 /* RIGHT */:
58 			gfuiFont[font]->output(x - gfuiFont[font]->getWidth(text), y, text);
59 			break;
60 	}
61 	glDisable(GL_ALPHA_TEST);
62 	glDisable(GL_TEXTURE_2D);
63 }
64 
GfuiFontHeight(int font)65 int GfuiFontHeight(int font)
66 {
67     return gfuiFont[font]->getHeight();
68 }
69 
GfuiFontWidth(int font,const char * text)70 int GfuiFontWidth(int font, const char *text)
71 {
72     return gfuiFont[font]->getWidth(text);
73 }
74 
75 void
GfuiDrawCursor()76 GfuiDrawCursor()
77 {
78     float xf = (float)(GfuiMouse.X);
79     float yf = (float)(GfuiMouse.Y);
80 
81 #define SCALE 1.3
82 
83     glColor4fv(GfuiScreen->mouseColor[0]) ;
84     glBegin(GL_TRIANGLES);
85     glVertex2f(xf, yf);
86     glVertex2f(xf + 4.8 * SCALE, yf - 10.4 * SCALE);
87     glVertex2f(xf + 6.4 * SCALE, yf - 6.4 * SCALE);
88     glEnd();
89 
90     glBegin(GL_QUADS);
91     glVertex2f(xf + 5.6 * SCALE, yf - 6.4 * SCALE);
92     glVertex2f(xf + 6 * SCALE, yf - 6 * SCALE);
93     glVertex2f(xf + 12.4 * SCALE, yf - 12.4 * SCALE);
94     glVertex2f(xf + 12 * SCALE, yf - 12.8 * SCALE);
95     glEnd();
96 
97     glColor4fv(GfuiScreen->mouseColor[1]) ;
98     glBegin(GL_TRIANGLES);
99     glVertex2f(xf, yf) ;
100     glVertex2f(xf + 10.4 * SCALE, yf - 4.8 * SCALE);
101     glVertex2f(xf + 6.4 * SCALE, yf - 6.4 * SCALE);
102     glEnd();
103 
104     glBegin(GL_QUADS);
105     glVertex2f(xf + 6 * SCALE, yf - 6 * SCALE);
106     glVertex2f(xf + 6.4 * SCALE, yf - 4.8 * SCALE);
107     glVertex2f(xf + 12.8 * SCALE, yf - 12 * SCALE);
108     glVertex2f(xf + 12.4 * SCALE, yf - 12.4 * SCALE);
109     glEnd();
110 
111 }
112 
113 void
GfuiDraw(tGfuiObject * obj)114 GfuiDraw(tGfuiObject *obj)
115 {
116     if (obj->visible) {
117 	switch (obj->widget){
118 	case GFUI_LABEL:
119 	    gfuiDrawLabel(obj);
120 	    break;
121 
122 	case GFUI_BUTTON:
123 	    gfuiDrawButton(obj);
124 	    break;
125 
126 	case GFUI_GRBUTTON:
127 	    gfuiDrawGrButton(obj);
128 	    break;
129 
130 	case GFUI_SCROLLIST:
131 	    gfuiDrawScrollist(obj);
132 	    break;
133 
134 	case GFUI_EDITBOX:
135 	    gfuiDrawEditbox(obj);
136 	    break;
137 
138 	case GFUI_IMAGE:
139 	    gfuiDrawImage(obj);
140 	    break;
141 	}
142     }
143 }
144 
145 
146 static int
gfuiMouseIn(tGfuiObject * obj)147 gfuiMouseIn(tGfuiObject *obj)
148 {
149     if ((GfuiMouse.X >= obj->xmin) &&
150 	(GfuiMouse.X <= obj->xmax) &&
151 	(GfuiMouse.Y >= obj->ymin) &&
152 	(GfuiMouse.Y <= obj->ymax)) {
153 	return 1;
154     }
155     return 0;
156 }
157 
158 /** Remove the focus on the current element.
159     @ingroup	gui
160 */
161 void
GfuiUnSelectCurrent(void)162 GfuiUnSelectCurrent(void)
163 {
164     tGfuiButton		*button;
165     tGfuiEditbox	*editbox;
166     tGfuiGrButton	*grbutton;
167     tGfuiObject		*obj;
168 
169     obj = GfuiScreen->hasFocus;
170     if (obj == NULL) {
171 	return;
172     }
173     GfuiScreen->hasFocus = (tGfuiObject*)NULL;
174     obj->focus = 0;
175     switch (obj->widget) {
176     case GFUI_BUTTON:
177 	button = &(obj->u.button);
178 	button->state = GFUI_BTN_RELEASED;
179 	if (button->onFocusLost != NULL) {
180 	    button->onFocusLost(button->userDataOnFocus);
181 	}
182 	break;
183     case GFUI_GRBUTTON:
184 	grbutton = &(obj->u.grbutton);
185 	grbutton->state = GFUI_BTN_RELEASED;
186 	if (grbutton->onFocusLost != NULL) {
187 	    grbutton->onFocusLost(grbutton->userDataOnFocus);
188 	}
189 	break;
190     case GFUI_EDITBOX:
191 	editbox = &(obj->u.editbox);
192 	editbox->state = GFUI_BTN_RELEASED;
193 	if (editbox->onFocusLost != NULL) {
194 	    editbox->onFocusLost(editbox->userDataOnFocus);
195 	}
196 	break;
197     }
198 }
199 
200 static void
gfuiLoseFocus(tGfuiObject * obj)201 gfuiLoseFocus(tGfuiObject *obj)
202 {
203 	if (obj->state == GFUI_DISABLE) {
204 		return;
205 	}
206 
207     tGfuiButton		*button;
208     tGfuiEditbox	*editbox;
209     tGfuiGrButton	*grbutton;
210 
211     GfuiScreen->hasFocus = (tGfuiObject*)NULL;
212     obj->focus = 0;
213     switch (obj->widget) {
214     case GFUI_BUTTON:
215 	button = &(obj->u.button);
216 	button->state = GFUI_BTN_RELEASED;
217 	if (button->onFocusLost != NULL) {
218 	    button->onFocusLost(button->userDataOnFocus);
219 	}
220 	break;
221     case GFUI_GRBUTTON:
222 	grbutton = &(obj->u.grbutton);
223 	grbutton->state = GFUI_BTN_RELEASED;
224 	if (grbutton->onFocusLost != NULL) {
225 	    grbutton->onFocusLost(grbutton->userDataOnFocus);
226 	}
227 	break;
228     case GFUI_EDITBOX:
229 	editbox = &(obj->u.editbox);
230 	editbox->state = GFUI_BTN_RELEASED;
231 	if (editbox->onFocusLost != NULL) {
232 	    editbox->onFocusLost(editbox->userDataOnFocus);
233 	}
234 	break;
235     }
236 }
237 
238 static void
gfuiSetFocus(tGfuiObject * obj)239 gfuiSetFocus(tGfuiObject *obj)
240 {
241 	if (obj->state == GFUI_DISABLE) {
242 		return;
243 	}
244 
245 	tGfuiButton		*button;
246     tGfuiEditbox	*editbox;
247     tGfuiGrButton	*grbutton;
248 
249     if (GfuiScreen->hasFocus != NULL) {
250 	gfuiLoseFocus(GfuiScreen->hasFocus);
251     }
252     GfuiScreen->hasFocus = obj;
253     obj->focus = 1;
254     switch (obj->widget) {
255     case GFUI_BUTTON:
256 	button = &(obj->u.button);
257 	if (button->onFocus != NULL) {
258 	    button->onFocus(button->userDataOnFocus);
259 	}
260 	break;
261     case GFUI_GRBUTTON:
262 	grbutton = &(obj->u.grbutton);
263 	if (grbutton->onFocus != NULL) {
264 	    grbutton->onFocus(grbutton->userDataOnFocus);
265 	}
266 	break;
267     case GFUI_EDITBOX:
268 	editbox = &(obj->u.editbox);
269 	if (editbox->onFocus != NULL) {
270 	    editbox->onFocus(editbox->userDataOnFocus);
271 	}
272 	break;
273     }
274 }
275 
276 void
gfuiUpdateFocus(void)277 gfuiUpdateFocus(void)
278 {
279     tGfuiObject *curObject;
280 
281     curObject = GfuiScreen->hasFocus;
282     if (curObject != NULL) {
283 	if (gfuiMouseIn(curObject)) {
284 	    return; /* focus has not changed */
285 	}
286 	if (curObject->focusMode != GFUI_FOCUS_MOUSE_CLICK) {
287 	    gfuiLoseFocus(GfuiScreen->hasFocus);
288 	    GfuiScreen->hasFocus = (tGfuiObject*)NULL;
289 	}
290     }
291 
292     /* Search for a new focused object */
293     curObject = GfuiScreen->objects;
294     if (curObject != NULL) {
295 	do {
296 	    curObject = curObject->next;
297 	    if ((curObject->visible == 0) ||
298 		(curObject->focusMode == GFUI_FOCUS_NONE) ||
299 		((curObject->focusMode == GFUI_FOCUS_MOUSE_CLICK) && (GfuiScreen->mouse == 0))) {
300 		continue;
301 	    }
302 	    if (gfuiMouseIn(curObject)) {
303 		gfuiSetFocus(curObject);
304 		break;
305 	    }
306 	} while (curObject != GfuiScreen->objects);
307     }
308 }
309 
310 void
gfuiSelectNext(void *)311 gfuiSelectNext(void * /* dummy */)
312 {
313     tGfuiObject *startObject;
314     tGfuiObject *curObject;
315 
316     startObject = GfuiScreen->hasFocus;
317     if (startObject == NULL) {
318 	startObject = GfuiScreen->objects;
319     }
320     if (startObject == NULL) {
321 	return;
322     }
323     curObject = startObject;
324     do {
325 	switch (curObject->widget) {
326 	case GFUI_SCROLLIST:
327 	    gfuiScrollListNextElt(curObject);
328 	    break;
329 
330 	default:
331 	    curObject = curObject->next;
332 	    if ((curObject->focusMode != GFUI_FOCUS_NONE) &&
333 		(curObject->state != GFUI_DISABLE) &&
334 		(curObject->visible)) {
335 		gfuiSetFocus(curObject);
336 		return;
337 	    }
338 	    break;
339 	}
340     } while (curObject != startObject);
341 }
342 
343 void
gfuiSelectPrev(void *)344 gfuiSelectPrev(void * /* dummy */)
345 {
346     tGfuiObject *startObject;
347     tGfuiObject *curObject;
348 
349     startObject = GfuiScreen->hasFocus;
350     if (startObject == NULL) {
351 	startObject = GfuiScreen->objects;
352 	if (startObject == NULL) {
353 	    return;
354 	}
355 	startObject = startObject->next;
356     }
357     curObject = startObject;
358     do {
359 	switch (curObject->widget) {
360 	case GFUI_SCROLLIST:
361 	    gfuiScrollListPrevElt(curObject);
362 	    break;
363 
364 	default:
365 	    curObject = curObject->prev;
366 	    if ((curObject->focusMode != GFUI_FOCUS_NONE) &&
367 		(curObject->state != GFUI_DISABLE) &&
368 		(curObject->visible)) {
369 		gfuiSetFocus(curObject);
370 		return;
371 	    }
372 	    break;
373 	}
374     } while (curObject != startObject);
375 }
376 
377 void
gfuiSelectId(void * scr,int id)378 gfuiSelectId(void *scr, int id)
379 {
380     tGfuiObject *curObject;
381     tGfuiScreen	*screen = (tGfuiScreen*)scr;
382 
383     curObject = screen->objects;
384     if (curObject != NULL) {
385 	do {
386 	    curObject = curObject->next;
387 	    if (curObject->id == id) {
388 		gfuiSetFocus(curObject);
389 		break;
390 	    }
391 	} while (curObject != screen->objects);
392     }
393 }
394 
395 /** Set/unset the visibility attribute of an object.
396     @param	scr	Screen
397     @param	id	Object id
398     @param	visible	GFUI_VISIBLE or GFUI_INVISIBLE
399     @return	<tt>0 ... </tt>Ok
400 		<br><tt>-1 .. </tt>Error
401     @ingroup	gui
402  */
403 int
GfuiVisibilitySet(void * scr,int id,int visible)404 GfuiVisibilitySet(void *scr, int id, int visible)
405 {
406     tGfuiObject *curObject;
407 
408     curObject = gfuiGetObject(scr, id);
409     if (curObject == NULL) {
410 	return -1;
411     }
412     switch(visible) {
413     case GFUI_VISIBLE:
414 	curObject->visible = GFUI_VISIBLE;
415 	break;
416     case GFUI_INVISIBLE:
417 	curObject->visible = GFUI_INVISIBLE;
418 	break;
419     default:
420 	return -1;
421     }
422     return 0;
423 }
424 
425 /** Enable / Disable an object
426     @param	scr	Screen
427     @param	id	Object id
428     @param	flag	GFUI_ENABLE or GFUI_DISABLE
429     @return	<tt>0 ... </tt>Ok
430 		<br><tt>-1 .. </tt>Error
431     @ingroup	gui
432  */
433 int
GfuiEnable(void * scr,int id,int flag)434 GfuiEnable(void *scr, int id, int flag)
435 {
436     tGfuiObject *curObject;
437 
438     curObject = gfuiGetObject(scr, id);
439     if (curObject == NULL) {
440 	return -1;
441     }
442     switch(flag) {
443     case GFUI_ENABLE:
444 	curObject->state = GFUI_ENABLE;
445 	break;
446     case GFUI_DISABLE:
447 	curObject->state = GFUI_DISABLE;
448 	break;
449     default:
450 	return -1;
451     }
452     return 0;
453 }
454 
455 void
gfuiMouseAction(void * vaction)456 gfuiMouseAction(void *vaction)
457 {
458     tGfuiObject *curObject;
459     long	action = (long)vaction;
460 
461     curObject = GfuiScreen->hasFocus;
462     if (curObject != NULL) {
463 		if (curObject->state == GFUI_DISABLE) {
464 			return;
465 		}
466 
467 		switch (curObject->widget) {
468 		case GFUI_BUTTON:
469 			gfuiButtonAction((int)action);
470 			break;
471 		case GFUI_GRBUTTON:
472 			gfuiGrButtonAction((int)action);
473 			break;
474 		case GFUI_SCROLLIST:
475 			gfuiScrollListAction((int)action);
476 			break;
477 		case GFUI_EDITBOX:
478 			gfuiEditboxAction((int)action);
479 			break;
480 		}
481     }
482 }
483 
484 void
gfuiAddObject(tGfuiScreen * screen,tGfuiObject * object)485 gfuiAddObject(tGfuiScreen *screen, tGfuiObject *object)
486 {
487     if (screen->objects == NULL) {
488 	screen->objects = object;
489 	object->next = object;
490 	object->prev = object;
491     } else {
492 	object->next = screen->objects->next;
493 	object->prev = screen->objects;
494 	screen->objects->next = object;
495 	object->next->prev = object;
496 	screen->objects = object;
497     }
498 }
499 
500 tGfuiObject *
gfuiGetObject(void * scr,int id)501 gfuiGetObject(void *scr, int id)
502 {
503     tGfuiObject *curObject;
504     tGfuiScreen	*screen = (tGfuiScreen*)scr;
505 
506     curObject = screen->objects;
507     if (curObject != NULL) {
508 	do {
509 	    curObject = curObject->next;
510 	    if (curObject->id == id) {
511 		return curObject;
512 	    }
513 	} while (curObject != screen->objects);
514     }
515     return (tGfuiObject *)NULL;
516 }
517 
518 
519 void
gfuiReleaseObject(tGfuiObject * curObject)520 gfuiReleaseObject(tGfuiObject *curObject)
521 {
522     switch (curObject->widget){
523     case GFUI_LABEL:
524 	gfuiReleaseLabel(curObject);
525 	break;
526 
527     case GFUI_BUTTON:
528 	gfuiReleaseButton(curObject);
529 	break;
530 
531     case GFUI_GRBUTTON:
532 	gfuiReleaseGrButton(curObject);
533 	break;
534 
535     case GFUI_SCROLLIST:
536 	gfuiReleaseScrollist(curObject);
537 	break;
538 
539     case GFUI_SCROLLBAR:
540 	gfuiReleaseScrollbar(curObject);
541 	break;
542 
543     case GFUI_EDITBOX:
544 	gfuiReleaseEditbox(curObject);
545 	break;
546     case GFUI_IMAGE:
547 	gfuiReleaseImage(curObject);
548 	break;
549     }
550 }
551