1 /*
2 * XPilotNG/SDL, an SDL/OpenGL XPilot client.
3 *
4 * Copyright (C) 2003-2004 Erik Andersson <maximan@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "xpclient_sdl.h"
22
23 #include "sdlpaint.h"
24 #include "images.h"
25 #include "text.h"
26 #include "glwidgets.h"
27 #include "scrap.h"
28
29 /****************************************************/
30 /* BEGIN: Main GLWidget stuff */
31 /****************************************************/
32
33 static void option_callback( void *opt, const char *value );
34 static void confmenu_callback( void );
35 static void hover_optionWidget( int over, Uint16 x , Uint16 y , void *data );
36 static void clear_eventTarget( GLWidget *widget );
37
38 static char *scrap = NULL;
39 static GLWidget *scraptarget = NULL;
40
Init_EmptyBaseGLWidget(void)41 GLWidget *Init_EmptyBaseGLWidget( void )
42 {
43 GLWidget *tmp = XMALLOC(GLWidget, 1);
44 if ( !tmp ) return NULL;
45 tmp->WIDGET = -1;
46 tmp->bounds.x = 0;
47 tmp->bounds.y = 0;
48 tmp->bounds.w = 0;
49 tmp->bounds.h = 0;
50 tmp->wid_info = NULL;
51 tmp->Draw = NULL;
52 tmp->Close = NULL;
53 tmp->SetBounds = NULL;
54 tmp->button = NULL;
55 tmp->buttondata = NULL;
56 tmp->motion = NULL;
57 tmp->motiondata = NULL;
58 tmp->hover = NULL;
59 tmp->hoverdata = NULL;
60 tmp->list = NULL;
61 tmp->children = NULL;
62 tmp->next = NULL;
63 return tmp;
64 }
65
clear_eventTarget(GLWidget * widget)66 static void clear_eventTarget( GLWidget *widget )
67 {
68 int i;
69
70 if (!widget) {
71 error("NULL passed to clear_eventTarget!");
72 return;
73 }
74
75 for (i=0;i<NUM_MOUSE_BUTTONS;++i)
76 if (widget == clicktarget[i]) clicktarget[i]=NULL;
77 if (widget == hovertarget) hovertarget=NULL;
78 if (widget == scraptarget) scraptarget=NULL;
79
80 }
81
82 /* only supposed to take care of mallocs done on behalf of the
83 * appropriate Init_<foo> function
84 */
Close_WidgetTree(GLWidget ** widget)85 static void Close_WidgetTree ( GLWidget **widget )
86 {
87 if (!widget) return;
88 if (!(*widget)) return;
89
90 Close_WidgetTree ( &((*widget)->next) );
91 Close_WidgetTree ( &((*widget)->children) );
92
93 if ((*widget)->Close) (*widget)->Close(*widget);
94
95 clear_eventTarget(*widget);
96
97 if ((*widget)->wid_info) free((*widget)->wid_info);
98 free(*widget);
99 *widget = NULL;
100 }
101
Close_Widget(GLWidget ** widget)102 void Close_Widget ( GLWidget **widget )
103 {
104 GLWidget *tmp;
105
106 if (!widget) {
107 error("NULL passed to Close_Widget!");
108 return;
109 }
110 if (!(*widget)) {
111 error("pointer passed to Close_Widget points to NULL !");
112 return;
113 }
114
115 Close_WidgetTree( &((*widget)->children) );
116
117 if ((*widget)->Close) (*widget)->Close(*widget);
118
119 clear_eventTarget(*widget);
120
121 tmp = *widget;
122 *widget = (*widget)->next;
123 free(tmp);
124 }
125
126 /* IMPORTANT: compound widgets need to edit this function */
SetBounds_GLWidget(GLWidget * widget,SDL_Rect * b)127 void SetBounds_GLWidget( GLWidget *widget, SDL_Rect *b )
128 {
129 if (!widget) {
130 error("NULL widget passed to SetBounds_GLWidget!");
131 return;
132 }
133 if (!b) {
134 error("NULL bounds passed to SetBounds_GLWidget!");
135 return;
136 }
137
138 if (widget->SetBounds) widget->SetBounds(widget,b);
139 else {
140 widget->bounds.x = b->x;
141 widget->bounds.y = b->y;
142 widget->bounds.w = b->w;
143 widget->bounds.h = b->h;
144 }
145 }
146
hover_optionWidget(int over,Uint16 x,Uint16 y,void * data)147 static void hover_optionWidget( int over, Uint16 x , Uint16 y , void *data )
148 {
149 static GLWidget *hoverWidget, *labelWidget;
150 xp_option_t *opt;
151 static SDL_Rect b;
152 const char *help;
153 static char line[256];
154 int start = 0, end = 0;
155 bool eternalLoop = true;
156 static Uint32 bgColor = 0x0000ff88;
157
158 if (over) {
159 if (!data) {
160 error("NULL option passed to hover_optionWidget\n");
161 return;
162 }
163
164 opt = (xp_option_t *)data;
165
166 if ((help = Option_get_help(opt))) {
167 if (!(hoverWidget = Init_ListWidget( x, y, &nullRGBA, &nullRGBA, &nullRGBA, DOWN, LEFT, VERTICAL, false ))) {
168 error("hover_optionWidget: Failed to create ListWidget\n");
169 return;
170 }
171
172 if (!(labelWidget = Init_LabelWidget( Option_get_name(opt), &yellowRGBA, &bgColor, CENTER, CENTER ))) {
173 error("hover_optionWidget: Failed to create LabelWidget\n");
174 Close_Widget(&hoverWidget);
175 return;
176 }
177 ListWidget_Append( hoverWidget , labelWidget );
178
179 for ( end=0 ; end < 1000000; ++end) {
180 if ( help[end] != '\n' && help[end] != '\0') {
181 continue;
182 }
183
184 if (start != end ) {
185 strncpy(&line[0],help+start,MIN(255,end-start));
186 line[MIN(255,end-start)]='\0';
187
188 if (!(labelWidget = Init_LabelWidget( &line[0], &whiteRGBA, &bgColor, CENTER, CENTER ))) {
189 error("hover_optionWidget: Failed to create LabelWidget\n");
190 Close_Widget(&hoverWidget);
191 return;
192 }
193 ListWidget_Append( hoverWidget , labelWidget );
194 }
195
196 start = end+1;
197 if (help[end] == '\0') {
198 eternalLoop = false;
199 break;
200 }
201 }
202
203 if (eternalLoop) error("hover_optionWidget: string parse never ends! (infinite loop prevented)\n");
204
205 AppendGLWidgetList( &(MainWidget->children), hoverWidget );
206
207 b.h = hoverWidget->bounds.h;
208 b.w = hoverWidget->bounds.w;
209 b.x = x - hoverWidget->bounds.w - 10;
210 b.y = y - hoverWidget->bounds.h/2;
211
212 SetBounds_GLWidget(hoverWidget,&b);
213 }
214 } else {
215 if (!hoverWidget)
216 return;
217 DelGLWidgetListItem( &(MainWidget->children), hoverWidget );
218 Close_Widget(&hoverWidget);
219 }
220 }
221
option_callback(void * tmp,const char * value)222 static void option_callback( void *tmp, const char *value )
223 {
224 xp_option_t *opt;
225
226 if (!(opt = (xp_option_t *)tmp)) {
227 error("Faulty parameter to option_callback: opt is a NULL pointer!");
228 return;
229 }
230
231 switch ( Option_get_type(opt) ) {
232 case xp_bool_option:
233 Set_bool_option( opt, *(opt->bool_ptr), xp_option_origin_config);
234 return;
235 case xp_int_option:
236 Set_int_option( opt, *(opt->int_ptr), xp_option_origin_config);
237 return;
238 case xp_double_option:
239 Set_double_option( opt, *(opt->dbl_ptr), xp_option_origin_config);
240 return;
241 case xp_string_option:
242 if (Option_get_flags(opt) & XP_OPTFLAG_CONFIG_COLORS) {
243 Set_string_option( opt, value, xp_option_origin_config);
244 return;
245 }
246 default:
247 return;
248 }
249 }
250
251 /* Eventually this will be the only visible initializer I guess */
Init_OptionWidget(xp_option_t * opt,Uint32 * fgcolor,Uint32 * bgcolor)252 GLWidget *Init_OptionWidget( xp_option_t *opt, Uint32 *fgcolor, Uint32 *bgcolor )
253 {
254 if (!opt) {
255 error("Faulty parameter to Init_DoubleChooserWidget: opt is a NULL pointer!");
256 return NULL;
257 }
258
259 switch ( Option_get_type(opt) ) {
260 case xp_bool_option:
261 if (Option_get_flags(opt) & XP_OPTFLAG_CONFIG_DEFAULT)
262 return Init_BoolChooserWidget(opt->name,opt->bool_ptr,fgcolor,bgcolor,option_callback,opt);
263 break;
264 case xp_int_option:
265 if (Option_get_flags(opt) & XP_OPTFLAG_CONFIG_DEFAULT)
266 return Init_IntChooserWidget(opt->name,opt->int_ptr,opt->int_minval,opt->int_maxval,fgcolor,bgcolor,option_callback,opt);
267 break;
268 case xp_double_option:
269 if (Option_get_flags(opt) & XP_OPTFLAG_CONFIG_DEFAULT)
270 return Init_DoubleChooserWidget(opt->name,opt->dbl_ptr,opt->dbl_minval,opt->dbl_maxval,fgcolor,bgcolor,option_callback,opt);
271 break;
272 case xp_string_option:
273 if (Option_get_flags(opt) & XP_OPTFLAG_CONFIG_COLORS)
274 return Init_ColorChooserWidget(opt->name,(Uint32 *)opt->private_data,fgcolor,bgcolor,option_callback,opt);
275 break;
276 default:
277 break;
278 }
279 return NULL;
280 }
281
AppendGLWidgetList(GLWidget ** list,GLWidget * item)282 bool AppendGLWidgetList( GLWidget **list, GLWidget *item )
283 {
284 GLWidget **curr;
285
286 if (!list) {
287 error("No list holder for AppendGLWidgetList %i");
288 return false;
289 }
290 if (!item) {
291 error("Null item sent to AppendGLWidgetList");
292 }
293
294 item->list = list;
295
296 curr = list;
297 while (*curr) {
298 /* Just a trivial check if item already is in the list
299 * doesn't check for item's trailers however!
300 * Make sure items aren't added twice!
301 */
302 if (*curr == item) {
303 error("AppendGLWidgetList: item is already in the list!");
304 return false;
305 }
306 curr = &((*curr)->next);
307 }
308 *curr = item;
309
310 return true;
311 }
312
PrependGLWidgetList(GLWidget ** list,GLWidget * item)313 void PrependGLWidgetList( GLWidget **list, GLWidget *item )
314 {
315 GLWidget **curr;
316
317 if (!list) {
318 error("No list holder for PrependGLWidgetList");
319 return;
320 }
321 if (!item) {
322 error("Null item sent to PrependGLWidgetList");
323 }
324
325 item->list = list;
326
327 curr = &item;
328 while (*curr) {
329 curr = &((*curr)->next);
330 }
331
332 *curr = *list;
333 *list = item;
334 }
335
DelGLWidgetListItem(GLWidget ** list,GLWidget * widget)336 bool DelGLWidgetListItem( GLWidget **list, GLWidget *widget )
337 {
338 GLWidget **curr;
339
340 if (!list) {
341 error("No list holder for DelGLWidgetListItem");
342 return false;
343 }
344 if (!widget) {
345 error("Null widget sent to DelGLWidgetListItem");
346 return false;
347 }
348
349 /* We don't clear widget->list here, because it still 'belongs'
350 * to list until we link it somewhere else
351 */
352
353 curr = list;
354 while (*curr) {
355 if (*curr == widget) {
356 *curr = (*curr)->next;
357 widget->next = NULL;
358 return true;
359 }
360 curr = &((*curr)->next);
361 }
362
363 return false;
364 }
365
366 /*
367 * Traverses a widget tree and calls Draw for each widget
368 * the order is widget then its children (first to last)
369 * then it moves onto the next widget in the list
370 */
DrawGLWidgetsi(GLWidget * list,int x,int y,int w,int h)371 void DrawGLWidgetsi( GLWidget *list, int x, int y, int w, int h)
372 {
373 int x2,y2,w2,h2;
374 GLWidget *curr;
375
376 curr = list;
377
378 while (curr) {
379 x2 = MAX(x,curr->bounds.x);
380 y2 = MAX(y,curr->bounds.y);
381 w2 = MIN(x+w,curr->bounds.x+curr->bounds.w) - x2;
382 h2 = MIN(y+h,curr->bounds.y+curr->bounds.h) - y2;
383 if ( (w2 > 0) && (h2 > 0) ) {
384 glEnable(GL_BLEND);
385 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
386 glScissor(x2, draw_height - y2 - h2, w2+1, h2+1);
387 if (curr->Draw) curr->Draw(curr);
388 glDisable(GL_BLEND);
389
390 DrawGLWidgetsi(curr->children,x2, y2, w2, h2);
391 glScissor(x, draw_height - y - h, w, h);
392 }
393
394 curr = curr->next;
395 }
396 }
DrawGLWidgets(GLWidget * list)397 void DrawGLWidgets( GLWidget *list )
398 {
399 glScissor(0, 0, draw_width, draw_height);
400 glEnable(GL_SCISSOR_TEST);
401 DrawGLWidgetsi( list , 0, 0, draw_width, draw_height );
402 glDisable(GL_SCISSOR_TEST);
403 }
404
405 /*
406 * Similar to DrawGLWidgets, but this one needs to traverse the
407 * tree in reverse order! (since the things painted last will
408 * be seen ontop, thus should get first pick of events
409 * So it will descend to the last child in the list's last widget
410 * then traverse back trying to find the target.
411 */
412 /*
413 * Possibly this function will be hidden, and
414 * GLWidget *FindGLWidget( Uint16 x, Uint16 y );
415 * visible only. (so that nobody passes a non-visible
416 * widget list)
417 */
FindGLWidgeti(GLWidget * widget,Uint16 x,Uint16 y)418 GLWidget *FindGLWidgeti( GLWidget *widget, Uint16 x, Uint16 y )
419 {
420 GLWidget *tmp;
421
422 if ( !widget ) return NULL;
423
424 if ( (tmp = FindGLWidgeti( widget->next, x, y )) ) {
425 return tmp;
426 }
427
428 if( (x >= widget->bounds.x) && (x <= (widget->bounds.x + widget->bounds.w))
429 && (y >= widget->bounds.y) && (y <= (widget->bounds.y + widget->bounds.h)) ) {
430 if ( (tmp = FindGLWidgeti( widget->children, x, y )) ) {
431 return tmp;
432 } else return widget;
433 } else {
434 return NULL;
435 }
436 }
FindGLWidget(GLWidget * list,Uint16 x,Uint16 y)437 GLWidget *FindGLWidget( GLWidget *list, Uint16 x, Uint16 y )
438 {
439 return FindGLWidgeti( list, x, y );
440 }
441
load_textscrap(char * text)442 void load_textscrap(char *text)
443 {
444 char *cp;
445 int i;
446
447 if (!text) return;
448
449 scraptarget = NULL;
450 scrap = realloc(scrap, strlen(text)+1);
451 strcpy(scrap, text);
452 for ( cp=scrap, i=0; i<(int)strlen(scrap); ++cp, ++i ) {
453 if ( *cp == '\n' )
454 *cp = '\r';
455 }
456 put_scrap(TextScrap('T','E','X','T'), strlen(scrap), scrap);
457 }
458 /****************************************************/
459 /* END: Main GLWidget stuff */
460 /****************************************************/
461
462 /**********************/
463 /* Begin: ArrowWidget*/
464 /**********************/
465 static void button_ArrowWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data );
466 static void Paint_ArrowWidget( GLWidget *widget );
467
button_ArrowWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)468 static void button_ArrowWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data )
469 {
470 ArrowWidget *tmp;
471
472 if (!data) return;
473 tmp = (ArrowWidget *)(((GLWidget *)data)->wid_info);
474 if (state == SDL_PRESSED && !(tmp->locked)) {
475 if (button == 1) {
476 tmp->press = true;
477 }
478 if (button == 2) {
479 tmp->tap = true;
480 if (tmp->action) tmp->action(tmp->actiondata);
481 }
482 }
483 if (state == SDL_RELEASED) {
484 if (button == 1) {
485 tmp->press = false;
486 }
487 }
488 }
489
Paint_ArrowWidget(GLWidget * widget)490 static void Paint_ArrowWidget( GLWidget *widget )
491 {
492 GLWidget *tmp;
493 SDL_Rect *b;
494 ArrowWidget *wid_info;
495 ArrowWidget_dir_t dir;
496 static Uint32 normalcolor = 0xff0000ff;
497 static Uint32 presscolor = 0x00ff00ff;
498 static Uint32 tapcolor = 0xffffffff;
499 static Uint32 lockcolor = 0x88000088;
500
501 if (!widget) return;
502
503 tmp = widget;
504 b = &(tmp->bounds);
505 wid_info = (ArrowWidget *)(tmp->wid_info);
506
507 if (wid_info->locked) {
508 set_alphacolor( lockcolor );
509 } else if (wid_info->press) {
510 if (wid_info->action) {
511 wid_info->action(wid_info->actiondata);
512 }
513 set_alphacolor( presscolor );
514 } else if (wid_info->tap) {
515 set_alphacolor( tapcolor );
516 wid_info->tap = false;
517 } else {
518 set_alphacolor( normalcolor );
519 }
520
521 dir = wid_info->direction;
522 glBegin(GL_POLYGON);
523 switch ( dir ) {
524 case RIGHTARROW:
525 glVertex2i(b->x ,b->y );
526 glVertex2i(b->x ,b->y+b->h );
527 glVertex2i(b->x + b->w ,b->y+b->h/2);
528 break;
529 case UPARROW:
530 glVertex2i(b->x + b->w/2,b->y );
531 glVertex2i(b->x ,b->y+b->h );
532 glVertex2i(b->x + b->w ,b->y+b->h );
533 break;
534 case LEFTARROW:
535 glVertex2i(b->x + b->w ,b->y );
536 glVertex2i(b->x ,b->y+b->h/2);
537 glVertex2i(b->x + b->w ,b->y+b->h );
538 break;
539 case DOWNARROW:
540 glVertex2i(b->x ,b->y );
541 glVertex2i(b->x + b->w/2,b->y+b->h );
542 glVertex2i(b->x + b->w ,b->y );
543 break;
544 default:
545 error("Weird direction for ArrowWidget! (direction:%i)\n",dir);
546 }
547 glEnd();
548 }
549
Init_ArrowWidget(ArrowWidget_dir_t direction,int width,int height,void (* action)(void * data),void * actiondata)550 GLWidget *Init_ArrowWidget( ArrowWidget_dir_t direction,int width, int height,
551 void (*action)( void *data), void *actiondata )
552 {
553 ArrowWidget *wid_info;
554 GLWidget *tmp = Init_EmptyBaseGLWidget();
555
556 if ( !tmp ) {
557 error("Failed to malloc in Init_ArrowWidget");
558 return NULL;
559 }
560 tmp->wid_info = malloc(sizeof(ArrowWidget));
561 if ( !(tmp->wid_info) ) {
562 free(tmp);
563 error("Failed to malloc in Init_ArrowWidget");
564 return NULL;
565 }
566 wid_info = (ArrowWidget *)tmp->wid_info;
567
568 tmp->WIDGET = ARROWWIDGET;
569 wid_info->direction = direction;
570 tmp->bounds.w = width;
571 tmp->bounds.h = height;
572 wid_info->press = false;
573 wid_info->tap = false;
574 wid_info->locked = false;
575 wid_info->action = action;
576 wid_info->actiondata= actiondata;
577 tmp->Draw = Paint_ArrowWidget;
578 tmp->button = button_ArrowWidget;
579 tmp->buttondata = tmp;
580
581 return tmp;
582 }
583
584 /********************/
585 /* End: ArrowWidget*/
586 /********************/
587
588 /**********************/
589 /* Begin: ButtonWidget*/
590 /**********************/
591 static void button_ButtonWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data );
592 static void Paint_ButtonWidget( GLWidget *widget );
593
button_ButtonWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)594 static void button_ButtonWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data )
595 {
596 ButtonWidget *tmp;
597
598 if (!data) return;
599 tmp = (ButtonWidget *)(((GLWidget *)data)->wid_info);
600 if (state == SDL_PRESSED) {
601 if (tmp->pressed) return;
602 if (button == 1) {
603 tmp->pressed = true;
604 tmp->press_time = loopsSlow;
605 if (tmp->action) tmp->action(tmp->actiondata);
606 }
607 }
608 }
609
Paint_ButtonWidget(GLWidget * widget)610 static void Paint_ButtonWidget( GLWidget *widget )
611 {
612 ButtonWidget *wid_info;
613 int color;
614
615 if (!widget) return;
616 if (!(wid_info = (ButtonWidget *)(widget->wid_info))) return;
617
618 if (wid_info->pressed) {
619 if (wid_info->pressed_color)
620 color = *(wid_info->pressed_color);
621 else color = redRGBA;
622 if (loopsSlow >= (int)(wid_info->press_time + wid_info->depress_time))
623 wid_info->pressed = false;
624 } else {
625 if (wid_info->normal_color)
626 color = *(wid_info->normal_color);
627 else color = greenRGBA;
628 }
629
630 set_alphacolor(color);
631 glBegin(GL_QUADS);
632 glVertex2i( widget->bounds.x , widget->bounds.y );
633 glVertex2i( widget->bounds.x , widget->bounds.y+widget->bounds.h );
634 glVertex2i( widget->bounds.x+widget->bounds.w , widget->bounds.y+widget->bounds.h );
635 glVertex2i( widget->bounds.x+widget->bounds.w , widget->bounds.y );
636 glEnd();
637 }
638
Init_ButtonWidget(Uint32 * normal_color,Uint32 * pressed_color,Uint8 depress_time,void (* action)(void * data),void * actiondata)639 GLWidget *Init_ButtonWidget( Uint32 *normal_color, Uint32 *pressed_color, Uint8 depress_time, void (*action)(void *data), void *actiondata)
640 {
641 ButtonWidget *wid_info;
642 GLWidget *tmp = Init_EmptyBaseGLWidget();
643
644 if ( !tmp ) {
645 error("Failed to malloc in Init_ButtonWidget");
646 return NULL;
647 }
648 tmp->wid_info = malloc(sizeof(ButtonWidget));
649 if ( !(tmp->wid_info) ) {
650 free(tmp);
651 error("Failed to malloc in Init_ButtonWidget");
652 return NULL;
653 }
654 wid_info = (ButtonWidget *)tmp->wid_info;
655
656 tmp->WIDGET = BUTTONWIDGET;
657 wid_info->pressed = false;
658 wid_info->normal_color = normal_color;
659 wid_info->pressed_color = pressed_color;
660 wid_info->depress_time = depress_time;
661 wid_info->action = action;
662 wid_info->actiondata = actiondata;
663 tmp->Draw = Paint_ButtonWidget;
664 tmp->button = button_ButtonWidget;
665 tmp->buttondata = tmp;
666
667 return tmp;
668 }
669
670 /********************/
671 /* End: ButtonWidget*/
672 /********************/
673
674 /**********************/
675 /* Begin: SlideWidget*/
676 /**********************/
677 static void button_SlideWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data );
678 static void Paint_SlideWidget( GLWidget *widget );
679
button_SlideWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)680 static void button_SlideWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data )
681 {
682 SlideWidget *tmp;
683
684 if (!data) return;
685
686 tmp = (SlideWidget *)(((GLWidget *)data)->wid_info);
687 if (state == SDL_PRESSED && !(tmp->sliding)) {
688 if (button == 1) {
689 tmp->sliding = true;
690 }
691 }
692 if (state == SDL_RELEASED) {
693 if (button == 1) {
694 tmp->sliding = false;
695 if (tmp->release) tmp->release(tmp->releasedata);
696 }
697 }
698 }
699
Paint_SlideWidget(GLWidget * widget)700 static void Paint_SlideWidget( GLWidget *widget )
701 {
702 GLWidget *tmp;
703 SDL_Rect *b;
704 SlideWidget *wid_info;
705
706
707 static Uint32 normalcolor = 0xff0000ff;
708 static Uint32 presscolor = 0x00ff00ff;
709 static Uint32 lockcolor = 0x333333ff;
710 Uint32 color;
711
712 if (!widget) return;
713 tmp = widget;
714 b = &(tmp->bounds);
715 wid_info = (SlideWidget *)(tmp->wid_info);
716
717 if (wid_info->locked) {
718 color = lockcolor;
719 } else if (wid_info->sliding) {
720 color = presscolor;
721 } else {
722 color = normalcolor;
723 }
724
725 glBegin(GL_QUADS);
726 set_alphacolor(color );
727 glVertex2i(b->x , b->y );
728 set_alphacolor(color );
729 glVertex2i(b->x + b->w , b->y );
730 set_alphacolor(color & 0xffffff77 );
731 glVertex2i(b->x + b->w , b->y + b->h );
732 set_alphacolor(color & 0xffffff77 );
733 glVertex2i(b->x , b->y + b->h );
734 glEnd();
735 }
736
Init_SlideWidget(bool locked,void (* motion)(Sint16 xrel,Sint16 yrel,Uint16 x,Uint16 y,void * data),void * motiondata,void (* release)(void * releasedata),void * releasedata)737 GLWidget *Init_SlideWidget( bool locked,
738 void (*motion)( Sint16 xrel, Sint16 yrel, Uint16 x, Uint16 y, void *data ), void *motiondata,
739 void (*release)(void *releasedata),void *releasedata )
740 {
741 SlideWidget *wid_info;
742 GLWidget *tmp = Init_EmptyBaseGLWidget();
743
744 if ( !tmp ) {
745 error("Failed to malloc in Init_SlideWidget");
746 return NULL;
747 }
748 tmp->wid_info = malloc(sizeof(SlideWidget));
749 if ( !(tmp->wid_info) ) {
750 free(tmp);
751 error("Failed to malloc in Init_SlideWidget");
752 return NULL;
753 }
754 wid_info = (SlideWidget *)tmp->wid_info;
755
756 tmp->WIDGET = SLIDEWIDGET;
757 tmp->bounds.x = 0;
758 tmp->bounds.y = 0;
759 tmp->bounds.w = 10;
760 tmp->bounds.h = 10;
761 wid_info->sliding = false;
762 wid_info->locked = locked;
763 wid_info->release = release;
764 wid_info->releasedata = releasedata;
765 tmp->Draw = Paint_SlideWidget;
766 tmp->button = button_SlideWidget;
767 tmp->buttondata = tmp;
768 tmp->motion = motion;
769 tmp->motiondata = motiondata;
770
771 return tmp;
772 }
773
774 /********************/
775 /* End: SlideWidget*/
776 /********************/
777
778 /*************************/
779 /* Begin: ScrollbarWidget*/
780 /*************************/
781 static void motion_ScrollbarWidget( Sint16 xrel, Sint16 yrel, Uint16 x, Uint16 y, void *data );
782 static void release_ScrollbarWidget( void *releasedata );
783 static void Paint_ScrollbarWidget( GLWidget *widget );
784 static void SetBounds_ScrollbarWidget( GLWidget *widget, SDL_Rect *b );
785 static void Close_ScrollbarWidget ( GLWidget *widget );
786
Close_ScrollbarWidget(GLWidget * widget)787 static void Close_ScrollbarWidget ( GLWidget *widget )
788 {
789 if (!widget) return;
790 if (widget->WIDGET !=SCROLLBARWIDGET) {
791 error("Wrong widget type for Close_ScrollbarWidget [%i]",widget->WIDGET);
792 return;
793 }
794 }
795
SetBounds_ScrollbarWidget(GLWidget * widget,SDL_Rect * b)796 static void SetBounds_ScrollbarWidget( GLWidget *widget, SDL_Rect *b )
797 {
798 ScrollbarWidget *tmp;
799 SDL_Rect sb;
800
801 if (!widget) return;
802 if (!b) return;
803 if (widget->WIDGET !=SCROLLBARWIDGET) {
804 error("Wrong widget type for SetBounds_ScrollbarWidget [%i]",widget->WIDGET);
805 return;
806 }
807
808 widget->bounds.x = b->x;
809 widget->bounds.y = b->y;
810 widget->bounds.w = b->w;
811 widget->bounds.h = b->h;
812
813 tmp = (ScrollbarWidget *)(widget->wid_info);
814
815 switch (tmp->dir) {
816 case SB_VERTICAL:
817 sb.x = b->x;
818 sb.w = b->w;
819 sb.y = b->y + (int)(b->h*tmp->pos);
820 sb.h = (int)(b->h*tmp->size);
821 break;
822 case SB_HORISONTAL:
823 sb.y = b->y;
824 sb.h = b->h;
825 sb.x = b->x + (int)(b->w*tmp->pos);
826 sb.w = (int)(b->w*tmp->size);
827 break;
828 default :
829 error("bad direction for Scrollbar in SetBounds_ScrollbarWidget!");
830 return;
831 }
832
833 SetBounds_GLWidget(tmp->slide,&sb);
834 }
835
Paint_ScrollbarWidget(GLWidget * widget)836 static void Paint_ScrollbarWidget( GLWidget *widget )
837 {
838 static Uint32 bgcolor = 0x00000044;
839 SDL_Rect *b = &(widget->bounds);
840
841 set_alphacolor( bgcolor );
842
843 glBegin(GL_QUADS);
844 glVertex2i(b->x , b->y);
845 glVertex2i(b->x + b->w , b->y);
846 glVertex2i(b->x + b->w , b->y + b->h);
847 glVertex2i(b->x , b->y + b->h);
848 glEnd();
849 }
850
motion_ScrollbarWidget(Sint16 xrel,Sint16 yrel,Uint16 x,Uint16 y,void * data)851 static void motion_ScrollbarWidget( Sint16 xrel, Sint16 yrel, Uint16 x, Uint16 y, void *data )
852 {
853 GLWidget *tmp;
854 ScrollbarWidget *wid_info;
855 GLWidget *slide;
856 Sint16 *coord1, coord2 = 0, min, max, size, move;
857 GLfloat oldpos;
858
859 if (!data) return;
860
861 tmp = (GLWidget *)data;
862 wid_info = (ScrollbarWidget *)tmp->wid_info;
863 slide = wid_info->slide;
864
865
866 switch (wid_info->dir) {
867 case SB_VERTICAL:
868 coord1 = &(slide->bounds.y);
869 min = tmp->bounds.y;
870 size = slide->bounds.h;
871 max = min + tmp->bounds.h;
872 move = yrel;
873 break;
874 case SB_HORISONTAL:
875 coord1 = &(slide->bounds.x);
876 min = tmp->bounds.x;
877 size = slide->bounds.w;
878 max = min + tmp->bounds.w;
879 move = xrel;
880 break;
881 default :
882 error("bad direction for Scrollbar in motion_ScrollbarWidget!");
883 return;
884 }
885
886 wid_info->oldmoves += move;
887
888 if (!(wid_info->oldmoves)) return;
889
890 if (wid_info->oldmoves > 0) {
891 coord2 = MIN(max-size,*coord1+wid_info->oldmoves);
892 } else if (wid_info->oldmoves < 0) {
893 coord2 = MAX(min,*coord1+wid_info->oldmoves);
894 }
895 wid_info->oldmoves -= coord2 - *coord1;
896 *coord1 = coord2;
897
898 oldpos = wid_info->pos;
899 wid_info->pos = ((GLfloat)(*coord1 - min))/((GLfloat)(max - min));
900
901 if ( (oldpos != wid_info->pos) && wid_info->poschange )
902 wid_info->poschange(wid_info->pos,wid_info->poschangedata);
903 }
904
release_ScrollbarWidget(void * releasedata)905 static void release_ScrollbarWidget( void *releasedata )
906 {
907 GLWidget *tmp;
908 ScrollbarWidget *wid_info;
909 if (!releasedata) return;
910
911 tmp = (GLWidget *)releasedata;
912 wid_info = (ScrollbarWidget *)tmp->wid_info;
913
914 wid_info->oldmoves = 0;
915 }
916
ScrollbarWidget_SetSlideSize(GLWidget * widget,GLfloat size)917 void ScrollbarWidget_SetSlideSize( GLWidget *widget, GLfloat size )
918 {
919 ScrollbarWidget *sb;
920
921 if (!widget) return;
922 if (widget->WIDGET !=SCROLLBARWIDGET) {
923 error("Wrong widget type for SetBounds_ScrollbarWidget [%i]",widget->WIDGET);
924 return;
925 }
926 if (!(sb = (ScrollbarWidget *)(widget->wid_info))) {
927 error("ScrollbarWidget_SetSlideSize: wid_info missing!");
928 return;
929 }
930
931 sb->size = MIN(1.0f,MAX(0.0f,size));
932
933 SetBounds_ScrollbarWidget(widget,&(widget->bounds));
934 }
935
Init_ScrollbarWidget(bool locked,GLfloat pos,GLfloat size,ScrollWidget_dir_t dir,void (* poschange)(GLfloat pos,void * poschangedata),void * poschangedata)936 GLWidget *Init_ScrollbarWidget( bool locked, GLfloat pos, GLfloat size, ScrollWidget_dir_t dir,
937 void (*poschange)( GLfloat pos , void *poschangedata),
938 void *poschangedata )
939 {
940 ScrollbarWidget *wid_info;
941 GLWidget *tmp = Init_EmptyBaseGLWidget();
942
943 if ( !tmp ) {
944 error("Failed to malloc in Init_ScrollbarWidget");
945 return NULL;
946 }
947 tmp->wid_info = malloc(sizeof(ScrollbarWidget));
948 if ( !(tmp->wid_info) ) {
949 free(tmp);
950 error("Failed to malloc in Init_ScrollbarWidget");
951 return NULL;
952 }
953 wid_info = (ScrollbarWidget *)tmp->wid_info;
954
955 tmp->WIDGET = SCROLLBARWIDGET;
956 tmp->bounds.w = 10;
957 tmp->bounds.h = 10;
958 tmp->Draw = Paint_ScrollbarWidget;
959 tmp->Close = Close_ScrollbarWidget;
960 tmp->SetBounds = SetBounds_ScrollbarWidget;
961 /*add pgUp, pgDown here later with button*/
962 wid_info->pos = MAX(0.0f,MIN(1.0f,pos));
963 wid_info->size = MAX(0.0f,MIN(1.0f,size));
964 wid_info->dir = dir;
965 wid_info->oldmoves = 0;
966 wid_info->poschange = poschange;
967 wid_info->poschangedata = poschangedata;
968 wid_info->slide = Init_SlideWidget(locked,motion_ScrollbarWidget, tmp, release_ScrollbarWidget, tmp);
969
970 if ( !(((ScrollbarWidget *)tmp->wid_info)->slide) ) {
971 error("Failed to make a SlideWidget for Init_ScrollbarWidget");
972 free(tmp->wid_info);
973 free(tmp);
974 return NULL;
975 }
976
977 AppendGLWidgetList(&(tmp->children), ((ScrollbarWidget *)tmp->wid_info)->slide);
978 return tmp;
979 }
980 /*************************/
981 /* End: ScrollbarWidget*/
982 /*************************/
983
984 /***********************/
985 /* Begin: LabelWidget*/
986 /***********************/
987 static void Paint_LabelWidget( GLWidget *widget );
988 static void Close_LabelWidget ( GLWidget *widget );
989
button_LabelWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)990 static void button_LabelWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data )
991 {
992 LabelWidget *tmp;
993
994 if (!data) return;
995 tmp = (LabelWidget *)(((GLWidget *)data)->wid_info);
996 if (state == SDL_PRESSED) {
997 if (button == 1) {
998 if ((tmp->tex).text) {
999 load_textscrap((tmp->tex).text);
1000 scraptarget = (GLWidget *)data;
1001 }
1002 }
1003 }
1004 }
1005
Close_LabelWidget(GLWidget * widget)1006 static void Close_LabelWidget( GLWidget *widget )
1007 {
1008 if (!widget) return;
1009 if (widget->WIDGET !=LABELWIDGET) {
1010 error("Wrong widget type for Close_LabelWidget [%i]",widget->WIDGET);
1011 return;
1012 }
1013 free_string_texture(&(((LabelWidget *)widget->wid_info)->tex));
1014 }
1015
LabelWidget_SetColor(GLWidget * widget,Uint32 * fgcolor,Uint32 * bgcolor)1016 bool LabelWidget_SetColor( GLWidget *widget , Uint32 *fgcolor, Uint32 *bgcolor )
1017 {
1018 LabelWidget *wi;
1019
1020 if (!widget) return false;
1021 if (widget->WIDGET !=LABELWIDGET) {
1022 error("Wrong widget type for LabelWidget_SetColor [%i]",widget->WIDGET);
1023 return false;
1024 }
1025
1026 if ( !(wi = (LabelWidget *)widget->wid_info) ) {
1027 error("LabelWidget_SetColor: widget->wid_info missing!");
1028 return false;
1029 }
1030 wi->bgcolor = bgcolor;
1031 wi->fgcolor = fgcolor;
1032
1033 return true;
1034 }
Paint_LabelWidget(GLWidget * widget)1035 static void Paint_LabelWidget( GLWidget *widget )
1036 {
1037 GLWidget *tmp;
1038 SDL_Rect *b;
1039 LabelWidget *wid_info;
1040 int x, y, alpha;
1041 Uint32 color;
1042 static int flasher = 0;
1043
1044 if (!widget) return;
1045
1046 tmp = widget;
1047 b = &(tmp->bounds);
1048 wid_info = (LabelWidget *)(tmp->wid_info);
1049
1050 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
1051 set_alphacolor(*(wid_info->bgcolor));
1052
1053 glBegin(GL_QUADS);
1054 glVertex2i(b->x ,b->y);
1055 glVertex2i(b->x + b->w ,b->y);
1056 glVertex2i(b->x + b->w ,b->y+b->h);
1057 glVertex2i(b->x ,b->y+b->h);
1058 glEnd();
1059 }
1060
1061 x = wid_info->align == LEFT ? tmp->bounds.x :
1062 wid_info->align == CENTER ? tmp->bounds.x + tmp->bounds.w / 2 :
1063 tmp->bounds.x + tmp->bounds.w;
1064 y = wid_info->valign == DOWN ? tmp->bounds.y :
1065 wid_info->valign == CENTER ? tmp->bounds.y + tmp->bounds.h / 2 :
1066 tmp->bounds.y + tmp->bounds.h;
1067
1068
1069 if ( wid_info->fgcolor )
1070 color = *(wid_info->fgcolor);
1071 else
1072 color = whiteRGBA;
1073
1074 if (scraptarget == tmp) {
1075 alpha = MAX(0,MIN(255,(color & 255) + tsin(flasher)*64));
1076 flasher += TABLE_SIZE/clientFPS;
1077 if (flasher >= TABLE_SIZE) flasher -= TABLE_SIZE;
1078
1079 color = (color&0xFFFFFF00) + alpha;
1080 }
1081
1082 disp_text(&(wid_info->tex),
1083 color,
1084 wid_info->align,
1085 wid_info->valign,
1086 x,
1087 draw_height - y,
1088 true);
1089 }
1090
Init_LabelWidget(const char * text,Uint32 * fgcolor,Uint32 * bgcolor,int align,int valign)1091 GLWidget *Init_LabelWidget( const char *text , Uint32 *fgcolor, Uint32 *bgcolor, int align, int valign )
1092 {
1093 GLWidget *tmp;
1094 LabelWidget *wid_info;
1095
1096 if (!text) {
1097 error("text missing for Init_LabelWidget.");
1098 return NULL;
1099 }
1100 tmp = Init_EmptyBaseGLWidget();
1101 if ( !tmp ) {
1102 error("Failed to malloc in Init_LabelWidget");
1103 return NULL;
1104 }
1105 tmp->wid_info = malloc(sizeof(LabelWidget));
1106 if ( !(tmp->wid_info) ) {
1107 free(tmp);
1108 error("Failed to malloc in Init_LabelWidget");
1109 return NULL;
1110 }
1111 wid_info = (LabelWidget *)tmp->wid_info;
1112
1113 if ( !render_text(&gamefont, text, &(((LabelWidget *)tmp->wid_info)->tex)) ) {
1114 free(tmp->wid_info);
1115 free(tmp);
1116 error("Failed to render text in Init_LabelWidget");
1117 return NULL;
1118 }
1119
1120 tmp->WIDGET = LABELWIDGET;
1121 tmp->bounds.w = (((LabelWidget *)tmp->wid_info)->tex).width;
1122 tmp->bounds.h = (((LabelWidget *)tmp->wid_info)->tex).height;
1123 wid_info->fgcolor = fgcolor;
1124 wid_info->bgcolor = bgcolor;
1125 wid_info->align = align;
1126 wid_info->valign = valign;
1127 tmp->Draw = Paint_LabelWidget;
1128 tmp->Close = Close_LabelWidget;
1129 tmp->button = button_LabelWidget;
1130 tmp->buttondata = tmp;
1131
1132 return tmp;
1133 }
1134 /********************/
1135 /* End: LabelWidget*/
1136 /********************/
1137
1138 /***********************************/
1139 /* Begin: LabeledRadiobuttonWidget*/
1140 /***********************************/
1141 static void button_LabeledRadiobuttonWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data );
1142 static void Paint_LabeledRadiobuttonWidget( GLWidget *widget );
1143
button_LabeledRadiobuttonWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)1144 static void button_LabeledRadiobuttonWidget( Uint8 button, Uint8 state, Uint16 x, Uint16 y, void *data )
1145 {
1146 LabeledRadiobuttonWidget *tmp;
1147 if (!data) return;
1148 tmp = (LabeledRadiobuttonWidget *)(((GLWidget *)data)->wid_info);
1149 if (state == SDL_PRESSED) {
1150 if (button == 1) {
1151 /* Toggle state, and call (*action)*/
1152 tmp->state = !(tmp->state);
1153 if (tmp->action) {
1154 tmp->action(tmp->state,tmp->actiondata);
1155 }
1156 }
1157 }
1158 }
1159
Paint_LabeledRadiobuttonWidget(GLWidget * widget)1160 static void Paint_LabeledRadiobuttonWidget( GLWidget *widget )
1161 {
1162 GLWidget *tmp;
1163 SDL_Rect *b;
1164 LabeledRadiobuttonWidget *wid_info;
1165 static Uint32 false_bg_color = 0x00000044;
1166 static Uint32 true_bg_color = 0x00000044;
1167 static Uint32 false_text_color = 0xff0000ff;
1168 static Uint32 true_text_color = 0x00ff00ff;
1169
1170 if (!widget) return;
1171
1172 tmp = widget;
1173 b = &(tmp->bounds);
1174 wid_info = (LabeledRadiobuttonWidget *)(tmp->wid_info);
1175
1176 if (wid_info->state)
1177 set_alphacolor(true_bg_color);
1178 else
1179 set_alphacolor(false_bg_color);
1180
1181 glBegin(GL_QUADS);
1182 glVertex2i(b->x ,b->y);
1183 glVertex2i(b->x + b->w ,b->y);
1184 glVertex2i(b->x + b->w ,b->y+b->h);
1185 glVertex2i(b->x ,b->y+b->h);
1186 glEnd();
1187
1188 if (wid_info->state) {
1189 disp_text(wid_info->ontex, true_text_color, CENTER, CENTER,tmp->bounds.x+tmp->bounds.w/2, draw_height - tmp->bounds.y-tmp->bounds.h/2, true);
1190 } else {
1191 disp_text(wid_info->offtex, false_text_color, CENTER, CENTER, tmp->bounds.x+tmp->bounds.w/2, draw_height - tmp->bounds.y-tmp->bounds.h/2, true);
1192 }
1193 }
1194
Init_LabeledRadiobuttonWidget(string_tex_t * ontex,string_tex_t * offtex,void (* action)(bool state,void * actiondata),void * actiondata,bool start_state)1195 GLWidget *Init_LabeledRadiobuttonWidget( string_tex_t *ontex, string_tex_t *offtex,
1196 void (*action)(bool state, void *actiondata),
1197 void *actiondata, bool start_state )
1198 {
1199 GLWidget *tmp;
1200 LabeledRadiobuttonWidget *wid_info;
1201
1202 if (!ontex || !(ontex->tex_list) || !offtex || !(offtex->tex_list) ) {
1203 error("texure(s) missing for Init_LabeledRadiobuttonWidget.");
1204 return NULL;
1205 }
1206 tmp = Init_EmptyBaseGLWidget();
1207 if ( !tmp ) {
1208 error("Failed to malloc in Init_LabeledRadiobuttonWidget");
1209 return NULL;
1210 }
1211 tmp->wid_info = malloc(sizeof(LabeledRadiobuttonWidget));
1212 if ( !(tmp->wid_info) ) {
1213 free(tmp);
1214 error("Failed to malloc in Init_LabeledRadiobuttonWidget");
1215 return NULL;
1216 }
1217 wid_info = (LabeledRadiobuttonWidget *)tmp->wid_info;
1218
1219 tmp->WIDGET = LABELEDRADIOBUTTONWIDGET;
1220 tmp->bounds.w = MAX(ontex->width,offtex->width)+5;
1221 tmp->bounds.h = MAX(ontex->height,offtex->height);
1222 wid_info->state = start_state;
1223 wid_info->ontex = ontex;
1224 wid_info->offtex = offtex;
1225 wid_info->action = action;
1226 wid_info->actiondata= actiondata;
1227 tmp->Draw = Paint_LabeledRadiobuttonWidget;
1228 tmp->button = button_LabeledRadiobuttonWidget;
1229 tmp->buttondata = tmp;
1230
1231 return tmp;
1232 }
1233 /*********************************/
1234 /* End: LabeledRadiobuttonWidget*/
1235 /*********************************/
1236
1237 /*****************************/
1238 /* Begin: BoolChooserWidget */
1239 /*****************************/
1240 static void Paint_BoolChooserWidget( GLWidget *widget );
1241 static void BoolChooserWidget_SetValue( bool state, void *data );
1242 static void Close_BoolChooserWidget ( GLWidget *widget );
1243 static void SetBounds_BoolChooserWidget( GLWidget *widget, SDL_Rect *b );
1244
1245 static int num_BoolChooserWidget = 0;
1246 static string_tex_t *BoolChooserWidget_ontex = NULL;
1247 static string_tex_t *BoolChooserWidget_offtex = NULL;
1248
Close_BoolChooserWidget(GLWidget * widget)1249 static void Close_BoolChooserWidget( GLWidget *widget )
1250 {
1251 if (!widget) return;
1252 if (widget->WIDGET !=BOOLCHOOSERWIDGET) {
1253 error("Wrong widget type for Close_BoolChooserWidget [%i]",widget->WIDGET);
1254 return;
1255 }
1256
1257 --num_BoolChooserWidget;
1258 if (!num_BoolChooserWidget) {
1259 free_string_texture(BoolChooserWidget_ontex);
1260 free(BoolChooserWidget_ontex);
1261 BoolChooserWidget_ontex = NULL;
1262 free_string_texture(BoolChooserWidget_offtex);
1263 free(BoolChooserWidget_offtex);
1264 BoolChooserWidget_offtex = NULL;
1265 }
1266 }
1267
SetBounds_BoolChooserWidget(GLWidget * widget,SDL_Rect * b)1268 static void SetBounds_BoolChooserWidget( GLWidget *widget, SDL_Rect *b )
1269 {
1270 GLWidget *tmp;
1271 SDL_Rect b2;
1272
1273 if (!widget) return;
1274 if (!b) return;
1275 if (widget->WIDGET !=BOOLCHOOSERWIDGET) {
1276 error("Wrong widget type for SetBounds_BoolChooserWidget [%i]",widget->WIDGET);
1277 return;
1278 }
1279
1280 widget->bounds.x = b->x;
1281 widget->bounds.y = b->y;
1282 widget->bounds.w = b->w;
1283 widget->bounds.h = b->h;
1284
1285 tmp = ((BoolChooserWidget *)(widget->wid_info))->buttonwidget;
1286
1287 b2.h = tmp->bounds.h;
1288 b2.w = tmp->bounds.w;
1289 b2.x = widget->bounds.x + widget->bounds.w - 2 - tmp->bounds.w;
1290 b2.y = widget->bounds.y + 1;
1291
1292 SetBounds_GLWidget(tmp,&b2);
1293
1294 tmp = ((BoolChooserWidget *)(widget->wid_info))->name;
1295
1296 b2.h = widget->bounds.h;
1297 b2.w = tmp->bounds.w;
1298 b2.x = widget->bounds.x + 2;
1299 b2.y = widget->bounds.y;
1300
1301 SetBounds_GLWidget(tmp,&b2);
1302 }
1303
BoolChooserWidget_SetValue(bool state,void * data)1304 static void BoolChooserWidget_SetValue( bool state, void *data )
1305 {
1306 GLWidget *wid;
1307 BoolChooserWidget *wi;
1308
1309 if ( !(wid = (GLWidget *)data) ) {
1310 error("BoolChooserWidget_SetValue: data missing!");
1311 return;
1312 }
1313
1314 if ( wid->WIDGET != BOOLCHOOSERWIDGET ) {
1315 error("BoolChooserWidget_SetValue: wrong type of widget!");
1316 return;
1317 }
1318
1319 if ( !(wi = (BoolChooserWidget *)(wid->wid_info)) ) {
1320 error("BoolChooserWidget_SetValue: wid_info missing!");
1321 return;
1322 }
1323
1324 *(wi->value) = state;
1325
1326 if (wi->callback)
1327 wi->callback( wi->data, NULL );
1328 }
1329
Paint_BoolChooserWidget(GLWidget * widget)1330 static void Paint_BoolChooserWidget( GLWidget *widget )
1331 {
1332 /*static int name_color = 0xffff66ff;*/
1333 BoolChooserWidget *wid_info;
1334
1335 if (!widget) {
1336 error("Paint_BoolChooserWidget: widget missing!");
1337 return;
1338 }
1339
1340 if ( widget->WIDGET != BOOLCHOOSERWIDGET ) {
1341 error("Paint_BoolChooserWidget: wrong type of widget!");
1342 return;
1343 }
1344
1345 if ( !(wid_info = (BoolChooserWidget *)(widget->wid_info)) ) {
1346 error("Paint_BoolChooserWidget: wid_info missing!");
1347 return;
1348 }
1349
1350 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
1351 set_alphacolor( *(wid_info->bgcolor) );
1352 glBegin(GL_QUADS);
1353 glVertex2i(widget->bounds.x ,widget->bounds.y );
1354 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y );
1355 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y+widget->bounds.h );
1356 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
1357 glEnd();
1358 }
1359 }
1360
Init_BoolChooserWidget(const char * name,bool * value,Uint32 * fgcolor,Uint32 * bgcolor,void (* callback)(void * tmp,const char * value),void * data)1361 GLWidget *Init_BoolChooserWidget( const char *name, bool *value, Uint32 *fgcolor, Uint32 *bgcolor,
1362 void (*callback)(void *tmp, const char *value), void *data )
1363 {
1364 GLWidget *tmp;
1365 BoolChooserWidget *wid_info;
1366
1367 if (!value) {
1368 error("Faulty parameter to Init_BoolChooserWidget: value is a NULL pointer!");
1369 return NULL;
1370 }
1371 if (!name || !strlen(name) ) {
1372 error("name misssing for Init_BoolChooserWidget.");
1373 return NULL;
1374 }
1375
1376
1377 if (!BoolChooserWidget_ontex) {
1378 if ((BoolChooserWidget_ontex = XMALLOC(string_tex_t, 1))) {
1379 if (!(BoolChooserWidget_offtex = XMALLOC(string_tex_t, 1))) {
1380 XFREE(BoolChooserWidget_ontex);
1381 error("Failed to malloc BoolChooserWidget_offtex in Init_BoolChooserWidget");
1382 return NULL;
1383 }
1384 } else {
1385 error("Failed to malloc BoolChooserWidget_ontex in Init_BoolChooserWidget");
1386 return NULL;
1387 }
1388 if (render_text(&gamefont,"True",BoolChooserWidget_ontex)) {
1389 if (!render_text(&gamefont,"False",BoolChooserWidget_offtex)) {
1390 error("Failed to render 'False' in Init_BoolChooserWidget");
1391 free_string_texture(BoolChooserWidget_ontex);
1392 XFREE(BoolChooserWidget_ontex);
1393 XFREE(BoolChooserWidget_offtex);
1394 return NULL;
1395 }
1396 } else {
1397 error("Failed to render 'True' in Init_BoolChooserWidget");
1398 XFREE(BoolChooserWidget_ontex);
1399 XFREE(BoolChooserWidget_offtex);
1400 return NULL;
1401 }
1402 }
1403
1404 tmp = Init_EmptyBaseGLWidget();
1405 if ( !tmp ) {
1406 error("Failed to malloc tmp in Init_BoolChooserWidget");
1407 return NULL;
1408 }
1409 tmp->wid_info = malloc(sizeof(BoolChooserWidget));
1410 if ( !(tmp->wid_info) ) {
1411 free(tmp);
1412 error("Failed to malloc tmp->wid_info in Init_BoolChooserWidget");
1413 return NULL;
1414 }
1415
1416 wid_info = (BoolChooserWidget *)(tmp->wid_info);
1417
1418 if ( !(wid_info->name = Init_LabelWidget(name,fgcolor,&nullRGBA,LEFT,CENTER)) ) {
1419 error("Failed to make a LabelWidget for Init_BoolChooserWidget");
1420 Close_Widget(&tmp);
1421 return NULL;
1422 }
1423 AppendGLWidgetList(&(tmp->children),wid_info->name);
1424
1425 wid_info->name->hover = hover_optionWidget;
1426 wid_info->name->hoverdata = data;
1427
1428 if ( !(wid_info->buttonwidget = Init_LabeledRadiobuttonWidget(BoolChooserWidget_ontex,
1429 BoolChooserWidget_offtex, BoolChooserWidget_SetValue,
1430 tmp, *(value))) ) {
1431 error("Failed to make a LabeledRadiobuttonWidget for Init_BoolChooserWidget");
1432 Close_Widget(&tmp);
1433 return NULL;
1434 }
1435 AppendGLWidgetList(&(tmp->children),wid_info->buttonwidget);
1436
1437 tmp->WIDGET = BOOLCHOOSERWIDGET;
1438 tmp->bounds.w = 2 + wid_info->name->bounds.w+5+wid_info->buttonwidget->bounds.w + 2;
1439 tmp->bounds.h = 1 + MAX( wid_info->name->bounds.h,wid_info->buttonwidget->bounds.h) + 1 ;
1440
1441 wid_info->value = value;
1442 wid_info->fgcolor = fgcolor;
1443 wid_info->bgcolor = bgcolor;
1444 wid_info->callback = callback;
1445 wid_info->data = data;
1446
1447 tmp->Draw = Paint_BoolChooserWidget;
1448 tmp->Close = Close_BoolChooserWidget;
1449 tmp->SetBounds = SetBounds_BoolChooserWidget;
1450
1451 ++num_BoolChooserWidget;
1452 return tmp;
1453 }
1454 /***************************/
1455 /* End: BoolChooserWidget */
1456 /***************************/
1457
1458 /***************************/
1459 /* Begin: IntChooserWidget */
1460 /***************************/
1461 static void IntChooserWidget_Add( void *data );
1462 static void IntChooserWidget_Subtract( void *data );
1463 static void Paint_IntChooserWidget( GLWidget *widget );
1464 static void Close_IntChooserWidget ( GLWidget *widget );
1465 static void SetBounds_IntChooserWidget( GLWidget *widget, SDL_Rect *b );
1466
Close_IntChooserWidget(GLWidget * widget)1467 static void Close_IntChooserWidget ( GLWidget *widget )
1468 {
1469 if (!widget) return;
1470 if (widget->WIDGET !=INTCHOOSERWIDGET) {
1471 error("Wrong widget type for Close_IntChooserWidget [%i]",widget->WIDGET);
1472 return;
1473 }
1474
1475 free_string_texture( &(((IntChooserWidget *)widget->wid_info)->valuetex) );
1476 }
1477
SetBounds_IntChooserWidget(GLWidget * widget,SDL_Rect * b)1478 static void SetBounds_IntChooserWidget( GLWidget *widget, SDL_Rect *b )
1479 {
1480 IntChooserWidget *tmp;
1481 GLWidget *tmp2;
1482 SDL_Rect rab,lab,b2;
1483
1484 if (!widget) return;
1485 if (!b) return;
1486 if (widget->WIDGET !=INTCHOOSERWIDGET) {
1487 error("Wrong widget type for SetBounds_IntChooserWidget [%i]",widget->WIDGET);
1488 return;
1489 }
1490
1491 widget->bounds.x = b->x;
1492 widget->bounds.y = b->y;
1493 widget->bounds.w = b->w;
1494 widget->bounds.h = b->h;
1495
1496 tmp = (IntChooserWidget *)(widget->wid_info);
1497
1498 lab.h = rab.h = tmp->valuetex.height-4;
1499 lab.w = rab.w = rab.h;
1500 lab.y = rab.y = widget->bounds.y + (widget->bounds.h-rab.h)/2;
1501 rab.x = widget->bounds.x + widget->bounds.w - rab.w -2/*>_|*/;
1502 lab.x = rab.x - tmp->valuespace/*_value*/ -2/*<_value_>*/ - lab.w;
1503
1504 SetBounds_GLWidget(tmp->leftarrow,&lab);
1505 SetBounds_GLWidget(tmp->rightarrow,&rab);
1506
1507 tmp2 = ((IntChooserWidget *)(widget->wid_info))->name;
1508
1509 b2.h = widget->bounds.h;
1510 b2.w = tmp2->bounds.w;
1511 b2.x = widget->bounds.x + 2;
1512 b2.y = widget->bounds.y;
1513
1514 SetBounds_GLWidget(tmp2,&b2);
1515 }
1516
IntChooserWidget_Add(void * data)1517 static void IntChooserWidget_Add( void *data )
1518 {
1519 IntChooserWidget *tmp;
1520 char valuetext[16];
1521 int step;
1522
1523 if (!data) return;
1524 tmp = ((IntChooserWidget *)((GLWidget *)data)->wid_info);
1525
1526 if (tmp->direction > 0) {
1527 step = (++tmp->duration)*(tmp->maxval-tmp->minval)/(MAX(1,MIN(maxFPS,FPS))*3);
1528 } else {
1529 step = 1;
1530 }
1531
1532 if (*(tmp->value) > tmp->maxval) {
1533 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = true;
1534 } else if (step) {
1535 tmp->duration = 0;
1536 *(tmp->value) = MIN( *(tmp->value) + step, tmp->maxval);
1537
1538 if (tmp->callback) tmp->callback( tmp->data, NULL );
1539
1540 if ( (*(tmp->value)) > tmp->minval)
1541 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = false;
1542 if ( (*(tmp->value)) == tmp->maxval)
1543 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = true;
1544 tmp->direction = 2;
1545 snprintf(valuetext,15,"%i",*(tmp->value));
1546 free_string_texture(&(tmp->valuetex));
1547 if(!render_text(&gamefont,valuetext,&(tmp->valuetex)))
1548 error("Failed to make value (%s=%i) texture for IntChooserWidget!\n",
1549 ((LabelWidget *)(tmp->name->wid_info))->tex.text,*(tmp->value));
1550 } else {
1551 ++tmp->direction;
1552 }
1553 }
1554
IntChooserWidget_Subtract(void * data)1555 static void IntChooserWidget_Subtract( void *data )
1556 {
1557 IntChooserWidget *tmp;
1558 char valuetext[16];
1559 int step;
1560
1561 if (!data) return;
1562 tmp = ((IntChooserWidget *)((GLWidget *)data)->wid_info);
1563
1564 if (tmp->direction < 0) {
1565 step = (++tmp->duration)*(tmp->maxval-tmp->minval)/(MAX(1,MIN(maxFPS,FPS))*3);
1566 } else {
1567 step = 1;
1568 }
1569
1570 if (*(tmp->value) < tmp->minval) {
1571 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = true;
1572 } else if (step) {
1573 tmp->duration = 0;
1574 *(tmp->value) = MAX( (*(tmp->value)) - step, tmp->minval);
1575
1576 if (tmp->callback) tmp->callback( tmp->data, NULL );
1577
1578 if ( (*(tmp->value)) < tmp->maxval)
1579 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = false;
1580 if ( (*(tmp->value)) == tmp->minval)
1581 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = true;
1582 tmp->direction = -2;
1583 snprintf(valuetext,15,"%i",*(tmp->value));
1584 free_string_texture(&(tmp->valuetex));
1585 if(!render_text(&gamefont,valuetext,&(tmp->valuetex)))
1586 error("Failed to make value (%s=%i) texture for IntChooserWidget!\n",
1587 ((LabelWidget *)(tmp->name->wid_info))->tex.text,*(tmp->value));
1588 } else {
1589 --tmp->direction;
1590 }
1591 }
1592
Paint_IntChooserWidget(GLWidget * widget)1593 static void Paint_IntChooserWidget( GLWidget *widget )
1594 {
1595 IntChooserWidget *wid_info;
1596
1597 if (!widget) {
1598 error("Paint_IntChooserWidget: argument is NULL!");
1599 return;
1600 }
1601
1602 wid_info = (IntChooserWidget *)(widget->wid_info);
1603
1604 if (!wid_info) {
1605 error("Paint_IntChooserWidget: wid_info missing");
1606 return;
1607 }
1608
1609 if (wid_info->direction > 0) --(wid_info->direction);
1610 else if (wid_info->direction < 0) ++(wid_info->direction);
1611
1612 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
1613 set_alphacolor(*(wid_info->bgcolor));
1614 glBegin(GL_QUADS);
1615 glVertex2i(widget->bounds.x ,widget->bounds.y );
1616 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y );
1617 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y+widget->bounds.h );
1618 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
1619 glEnd();
1620 }
1621 if ( wid_info->fgcolor )
1622 disp_text(&(wid_info->valuetex), *(wid_info->fgcolor), RIGHT, CENTER, wid_info->rightarrow->bounds.x-1/*value_>*/-2/*>_|*/, draw_height - widget->bounds.y - widget->bounds.h/2, true );
1623 else
1624 disp_text(&(wid_info->valuetex), whiteRGBA, RIGHT, CENTER, wid_info->rightarrow->bounds.x-1/*value_>*/-2/*>_|*/, draw_height - widget->bounds.y - widget->bounds.h/2, true );
1625 }
1626
Init_IntChooserWidget(const char * name,int * value,int minval,int maxval,Uint32 * fgcolor,Uint32 * bgcolor,void (* callback)(void * tmp,const char * value),void * data)1627 GLWidget *Init_IntChooserWidget( const char *name, int *value, int minval, int maxval, Uint32 *fgcolor,
1628 Uint32 *bgcolor, void (*callback)(void *tmp, const char *value), void *data )
1629 {
1630 int valuespace;
1631 GLWidget *tmp;
1632 IntChooserWidget *wid_info;
1633 char valuetext[16];
1634 string_tex_t tmp_tex;
1635 int buttonsize;
1636
1637 if (!value) {
1638 error("Faulty parameter to Init_IntChooserWidget: value is a NULL pointer!");
1639 return NULL;
1640 }
1641 if (!(name) || !strlen(name) ) {
1642 error("name misssing for Init_IntChooserWidget.");
1643 return NULL;
1644 }
1645
1646 tmp = Init_EmptyBaseGLWidget();
1647 if ( !tmp ) {
1648 error("Failed to malloc in Init_IntChooserWidget");
1649 return NULL;
1650 }
1651 tmp->wid_info = malloc(sizeof(IntChooserWidget));
1652 if ( !(tmp->wid_info) ) {
1653 free(tmp);
1654 error("Failed to malloc in Init_IntChooserWidget");
1655 return NULL;
1656 }
1657
1658 /* hehe ugly hack to guess max size of value strings
1659 * monospace font is preferred
1660 */
1661 if (render_text(&gamefont,"555.55",&tmp_tex)) {
1662 free_string_texture(&tmp_tex);
1663 valuespace = tmp_tex.width+4;
1664 } else {
1665 valuespace = 50;
1666 }
1667
1668 wid_info = (IntChooserWidget *)tmp->wid_info;
1669
1670 snprintf(valuetext,15,"%i",*(value));
1671 if(!render_text(&gamefont,valuetext,&(wid_info->valuetex))) {
1672 Close_Widget(&tmp);
1673 error("Init_IntChooserWidget: Failed to render value string");
1674 return NULL;
1675 }
1676 buttonsize = wid_info->valuetex.height-4;
1677
1678 tmp->WIDGET = INTCHOOSERWIDGET;
1679 tmp->Draw = Paint_IntChooserWidget;
1680 tmp->Close = Close_IntChooserWidget;
1681 tmp->SetBounds = SetBounds_IntChooserWidget;
1682 wid_info->value = value;
1683 wid_info->minval = minval;
1684 wid_info->maxval = maxval;
1685 wid_info->valuespace= valuespace;
1686 wid_info->direction = 0;
1687 wid_info->fgcolor = fgcolor;
1688 wid_info->bgcolor = bgcolor;
1689 wid_info->callback = callback;
1690 wid_info->data = data;
1691
1692
1693 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->name = Init_LabelWidget(name,fgcolor,&nullRGBA,LEFT,CENTER))) ) {
1694 Close_Widget(&tmp);
1695 error("Init_IntChooserWidget: Failed to initialize label [%s]",name);
1696 return NULL;
1697 }
1698
1699 wid_info->name->hover = hover_optionWidget;
1700 wid_info->name->hoverdata = data;
1701
1702 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->leftarrow = Init_ArrowWidget(LEFTARROW,buttonsize,buttonsize,IntChooserWidget_Subtract,tmp))) ) {
1703 Close_Widget(&tmp);
1704 error("Init_IntChooserWidget couldn't init leftarrow!");
1705 return NULL;
1706 }
1707
1708 if (*(wid_info->value) <= wid_info->minval) ((ArrowWidget *)(wid_info->leftarrow->wid_info))->locked = true;
1709
1710 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->rightarrow = Init_ArrowWidget(RIGHTARROW,buttonsize,buttonsize,IntChooserWidget_Add,tmp))) ) {
1711 Close_Widget(&tmp);
1712 error("Init_IntChooserWidget couldn't init rightarrow!");
1713 return NULL;
1714 }
1715
1716 if (*(wid_info->value) >= wid_info->maxval) ((ArrowWidget *)(wid_info->rightarrow->wid_info))->locked = true;
1717
1718 tmp->bounds.w = 2/*|_text*/+ wid_info->name->bounds.w +5/*text___<*/ + valuespace/*__value*/ + 2/*<_value_>*/
1719 + wid_info->leftarrow->bounds.w + wid_info->rightarrow->bounds.w +2/*>_|*/;
1720 tmp->bounds.h = wid_info->name->bounds.h;
1721
1722 return tmp;
1723 }
1724 /*************************/
1725 /* End: IntChooserWidget */
1726 /*************************/
1727
1728 /******************************/
1729 /* Begin: DoubleChooserWidget */
1730 /******************************/
1731 static void DoubleChooserWidget_Add( void *data );
1732 static void DoubleChooserWidget_Subtract( void *data );
1733 static void Paint_DoubleChooserWidget( GLWidget *widget );
1734 static void Close_DoubleChooserWidget ( GLWidget *widget );
1735 static void SetBounds_DoubleChooserWidget( GLWidget *widget, SDL_Rect *b );
1736
Close_DoubleChooserWidget(GLWidget * widget)1737 static void Close_DoubleChooserWidget ( GLWidget *widget )
1738 {
1739 if (!widget) return;
1740 if (widget->WIDGET !=DOUBLECHOOSERWIDGET) {
1741 error("Wrong widget type for Close_DoubleChooserWidget [%i]",widget->WIDGET);
1742 return;
1743 }
1744
1745 free_string_texture( &(((DoubleChooserWidget *)widget->wid_info)->valuetex) );
1746 }
1747
SetBounds_DoubleChooserWidget(GLWidget * widget,SDL_Rect * b)1748 static void SetBounds_DoubleChooserWidget( GLWidget *widget, SDL_Rect *b )
1749 {
1750 DoubleChooserWidget *tmp;
1751 GLWidget *tmp2;
1752 SDL_Rect rab,lab,b2;
1753
1754 if (!widget) return;
1755 if (!b) return;
1756 if (widget->WIDGET !=DOUBLECHOOSERWIDGET) {
1757 error("Wrong widget type for SetBounds_DoubleChooserWidget [%i]",widget->WIDGET);
1758 return;
1759 }
1760
1761 widget->bounds.x = b->x;
1762 widget->bounds.y = b->y;
1763 widget->bounds.w = b->w;
1764 widget->bounds.h = b->h;
1765
1766 tmp = (DoubleChooserWidget *)(widget->wid_info);
1767
1768 lab.h = rab.h = tmp->valuetex.height-4;
1769 lab.w = rab.w = rab.h;
1770 lab.y = rab.y = widget->bounds.y + (widget->bounds.h-rab.h)/2;
1771 rab.x = widget->bounds.x + widget->bounds.w - rab.w -2/*>_|*/;
1772 lab.x = rab.x - tmp->valuespace/*_value*/ -2/*<_value_>*/ - lab.w;
1773
1774 SetBounds_GLWidget(tmp->leftarrow,&lab);
1775 SetBounds_GLWidget(tmp->rightarrow,&rab);
1776
1777 tmp2 = ((DoubleChooserWidget *)(widget->wid_info))->name;
1778
1779 b2.h = widget->bounds.h;
1780 b2.w = tmp2->bounds.w;
1781 b2.x = widget->bounds.x + 2;
1782 b2.y = widget->bounds.y;
1783
1784 SetBounds_GLWidget(tmp2,&b2);
1785 }
1786
DoubleChooserWidget_Add(void * data)1787 static void DoubleChooserWidget_Add( void *data )
1788 {
1789 DoubleChooserWidget *tmp;
1790 double step;
1791 char valuetext[16];
1792
1793 if (!data) return;
1794 tmp = ((DoubleChooserWidget *)((GLWidget *)data)->wid_info);
1795
1796 if (tmp->direction > 0)
1797 step = (tmp->maxval-tmp->minval)/(clientFPS*10.0);
1798 else
1799 step = 0.01;
1800
1801 if ( *(tmp->value) < tmp->maxval ) {
1802 *(tmp->value) = MIN( (*(tmp->value))+step,tmp->maxval );
1803
1804 if ( tmp->callback ) tmp->callback( tmp->data, NULL );
1805
1806 if ( (*(tmp->value)) > tmp->minval )
1807 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = false;
1808 if ( (*(tmp->value)) >= tmp->maxval )
1809 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = true;
1810 tmp->direction = 2;
1811 snprintf(valuetext,15,"%1.2f",*(tmp->value));
1812 free_string_texture(&(tmp->valuetex));
1813 if(!render_text(&gamefont,valuetext,&(tmp->valuetex)))
1814 error("Failed to make value (%s=%1.2f) texture for doubleChooserWidget!\n",
1815 ((LabelWidget *)(tmp->name->wid_info))->tex.text,*(tmp->value));
1816 } else {
1817 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = true;
1818 }
1819 }
1820
DoubleChooserWidget_Subtract(void * data)1821 static void DoubleChooserWidget_Subtract( void *data )
1822 {
1823 DoubleChooserWidget *tmp;
1824 double step;
1825 char valuetext[16];
1826
1827 if (!data) return;
1828 tmp = ((DoubleChooserWidget *)((GLWidget *)data)->wid_info);
1829
1830 if (tmp->direction < 0)
1831 step = (tmp->maxval-tmp->minval)/(clientFPS*10.0);
1832 else
1833 step = 0.01;
1834
1835 if ( *(tmp->value) > tmp->minval ) {
1836 *(tmp->value) = MAX( (*(tmp->value))-step,tmp->minval );
1837
1838 if ( tmp->callback ) tmp->callback( tmp->data, NULL );
1839
1840 if ( (*(tmp->value)) < tmp->maxval )
1841 ((ArrowWidget *)tmp->rightarrow->wid_info)->locked = false;
1842 if ( (*(tmp->value)) <= tmp->minval )
1843 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = true;
1844 tmp->direction = -2;
1845 snprintf(valuetext,15,"%1.2f",*(tmp->value));
1846 free_string_texture(&(tmp->valuetex));
1847 if(!render_text(&gamefont,valuetext,&(tmp->valuetex)))
1848 error("Failed to make value (%s=%1.2f) texture for doubleChooserWidget!\n",
1849 ((LabelWidget *)(tmp->name->wid_info))->tex.text,*(tmp->value));
1850 } else {
1851 ((ArrowWidget *)tmp->leftarrow->wid_info)->locked = true;
1852 }
1853 }
1854
Paint_DoubleChooserWidget(GLWidget * widget)1855 static void Paint_DoubleChooserWidget( GLWidget *widget )
1856 {
1857 DoubleChooserWidget *wid_info;
1858
1859 if (!widget) {
1860 error("Paint_DoubleChooserWidget: argument is NULL!");
1861 return;
1862 }
1863
1864 wid_info = (DoubleChooserWidget *)(widget->wid_info);
1865
1866 if (!wid_info) {
1867 error("Paint_DoubleChooserWidget: wid_info missing");
1868 return;
1869 }
1870
1871 if (wid_info->direction > 0) --(wid_info->direction);
1872 else if (wid_info->direction < 0) ++(wid_info->direction);
1873
1874 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
1875 set_alphacolor(*(wid_info->bgcolor));
1876 glBegin(GL_QUADS);
1877 glVertex2i(widget->bounds.x ,widget->bounds.y );
1878 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y );
1879 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y+widget->bounds.h );
1880 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
1881 glEnd();
1882 }
1883
1884 if ( wid_info->fgcolor )
1885 disp_text(&(wid_info->valuetex), *(wid_info->fgcolor), RIGHT, CENTER, wid_info->rightarrow->bounds.x-1/*value_>*/-2/*>_|*/, draw_height - widget->bounds.y - widget->bounds.h/2, true );
1886 else
1887 disp_text(&(wid_info->valuetex), whiteRGBA, RIGHT, CENTER, wid_info->rightarrow->bounds.x-1/*value_>*/-2/*>_|*/, draw_height - widget->bounds.y - widget->bounds.h/2, true );
1888 }
1889
Init_DoubleChooserWidget(const char * name,double * value,double minval,double maxval,Uint32 * fgcolor,Uint32 * bgcolor,void (* callback)(void * tmp,const char * value),void * data)1890 GLWidget *Init_DoubleChooserWidget( const char *name, double *value, double minval, double maxval,
1891 Uint32 *fgcolor, Uint32 *bgcolor,
1892 void (*callback)(void *tmp, const char *value), void *data )
1893 {
1894 int valuespace;
1895 GLWidget *tmp;
1896 string_tex_t tmp_tex;
1897 DoubleChooserWidget *wid_info;
1898 char valuetext[16];
1899 int buttonsize;
1900
1901 if (!value) {
1902 error("Faulty parameter to Init_DoubleChooserWidget: value is a NULL pointer!");
1903 return NULL;
1904 }
1905 if (!(name) || !strlen(name) ) {
1906 error("name misssing for Init_DoubleChooserWidget.");
1907 return NULL;
1908 }
1909
1910 tmp = Init_EmptyBaseGLWidget();
1911 if ( !tmp ) {
1912 error("Failed to malloc in Init_DoubleChooserWidget");
1913 return NULL;
1914 }
1915 tmp->wid_info = XMALLOC(DoubleChooserWidget, 1);
1916 if ( !(tmp->wid_info) ) {
1917 free(tmp);
1918 error("Failed to malloc in Init_DoubleChooserWidget");
1919 return NULL;
1920 }
1921
1922 /* hehe ugly hack to guess max size of value strings
1923 * monospace font is preferred
1924 */
1925 if (render_text(&gamefont,"555.55",&tmp_tex)) {
1926 free_string_texture(&tmp_tex);
1927 valuespace = tmp_tex.width+4;
1928 } else {
1929 valuespace = 50;
1930 }
1931
1932 wid_info = (DoubleChooserWidget *)tmp->wid_info;
1933
1934 snprintf(valuetext,15,"%1.2f",*(value));
1935 if(!render_text(&gamefont,valuetext,&(wid_info->valuetex))) {
1936 Close_Widget(&tmp);
1937 error("Init_DoubleChooserWidget: Failed to render value string");
1938 return NULL;
1939 }
1940 buttonsize = wid_info->valuetex.height-4;
1941
1942 tmp->WIDGET = DOUBLECHOOSERWIDGET;
1943 tmp->Draw = Paint_DoubleChooserWidget;
1944 tmp->Close = Close_DoubleChooserWidget;
1945 tmp->SetBounds = SetBounds_DoubleChooserWidget;
1946 wid_info->value = value;
1947 wid_info->minval = minval;
1948 wid_info->maxval = maxval;
1949 wid_info->valuespace = valuespace;
1950 wid_info->direction = 0;
1951 wid_info->fgcolor = fgcolor;
1952 wid_info->bgcolor = bgcolor;
1953 wid_info->callback = callback;
1954 wid_info->data = data;
1955
1956 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->name = Init_LabelWidget(name,fgcolor,&nullRGBA,LEFT,CENTER))) ) {
1957 Close_Widget(&tmp);
1958 error("Init_DoubleChooserWidget: Failed to initialize label [%s]",name);
1959 return NULL;
1960 }
1961
1962 wid_info->name->hover = hover_optionWidget;
1963 wid_info->name->hoverdata = data;
1964
1965 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->leftarrow = Init_ArrowWidget(LEFTARROW,buttonsize,buttonsize,DoubleChooserWidget_Subtract,tmp))) ) {
1966 Close_Widget(&tmp);
1967 error("Init_DoubleChooserWidget: couldn't init leftarrow!");
1968 return NULL;
1969 }
1970
1971 if (*(wid_info->value) <= wid_info->minval) ((ArrowWidget *)(wid_info->leftarrow->wid_info))->locked = true;
1972
1973 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->rightarrow = Init_ArrowWidget(RIGHTARROW,buttonsize,buttonsize,DoubleChooserWidget_Add,tmp))) ) {
1974 Close_Widget(&tmp);
1975 error("Init_DoubleChooserWidget: couldn't init rightarrow!");
1976 return NULL;
1977 }
1978
1979 if (*(wid_info->value) >= wid_info->maxval) ((ArrowWidget *)(wid_info->rightarrow->wid_info))->locked = true;
1980
1981 tmp->bounds.w = 2/*|_text*/+ wid_info->name->bounds.w +5/*text___<*/ + valuespace/*__value*/ + 2/*<_value_>*/
1982 + wid_info->leftarrow->bounds.w + wid_info->rightarrow->bounds.w +2/*>_|*/;
1983 tmp->bounds.h = wid_info->name->bounds.h;
1984
1985 return tmp;
1986 }
1987 /****************************/
1988 /* End: DoubleChooserWidget */
1989 /****************************/
1990
1991 /*****************************/
1992 /* Begin: ColorChooserWidget */
1993 /*****************************/
1994 static void Paint_ColorChooserWidget( GLWidget *widget );
1995 static void SetBounds_ColorChooserWidget( GLWidget *widget, SDL_Rect *b );
1996 static void action_ColorChooserWidget(void *data);
1997
SetBounds_ColorChooserWidget(GLWidget * widget,SDL_Rect * b)1998 static void SetBounds_ColorChooserWidget( GLWidget *widget, SDL_Rect *b )
1999 {
2000 ColorChooserWidget *wid_info;
2001 GLWidget *name,*button,*m;
2002 SDL_Rect b2;
2003
2004 if (!widget) return;
2005 if (!b) return;
2006 if (widget->WIDGET !=COLORCHOOSERWIDGET) {
2007 error("Wrong widget type for SetBounds_ColorChooserWidget [%i]",widget->WIDGET);
2008 return;
2009 }
2010 if (!(wid_info = (ColorChooserWidget *)(widget->wid_info) )) {
2011 error("SetBounds_ColorChooserWidget: wid_info missing");
2012 return;
2013 }
2014
2015 name = ((ColorChooserWidget *)(widget->wid_info))->name;
2016 button = ((ColorChooserWidget *)(widget->wid_info))->button;
2017 m = ((ColorChooserWidget *)(widget->wid_info))->mod;
2018
2019 widget->bounds.x = b->x;
2020 widget->bounds.y = b->y;
2021 widget->bounds.w = b->w;
2022 widget->bounds.h = b->h;
2023
2024 b2.h = name->bounds.h;
2025 b2.w = name->bounds.w;
2026 b2.x = widget->bounds.x + 2;
2027 b2.y = widget->bounds.y;
2028
2029 SetBounds_GLWidget(name,&b2);
2030
2031 b2.h = name->bounds.h - 4;
2032 b2.w = b2.h;
2033 b2.x = widget->bounds.x + widget->bounds.w - 2 - b2.w;
2034 b2.y = widget->bounds.y + 2;
2035
2036 SetBounds_GLWidget(button,&b2);
2037
2038 if (wid_info->expanded && m) {
2039
2040 b2.h = m->bounds.h;
2041 b2.w = widget->bounds.w;
2042 b2.x = widget->bounds.x;
2043 b2.y = widget->bounds.y + name->bounds.h;
2044
2045 SetBounds_GLWidget(m,&b2);
2046 }
2047 }
2048
Paint_ColorChooserWidget(GLWidget * widget)2049 static void Paint_ColorChooserWidget( GLWidget *widget )
2050 {
2051 ColorChooserWidget *wid_info;
2052
2053 if (!widget) {
2054 error("Paint_ColorChooserWidget: argument is NULL!");
2055 return;
2056 }
2057
2058 wid_info = (ColorChooserWidget *)(widget->wid_info);
2059
2060 if (!wid_info) {
2061 error("Paint_ColorChooserWidget: wid_info missing");
2062 return;
2063 }
2064
2065 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
2066 set_alphacolor(*(wid_info->bgcolor));
2067 glBegin(GL_QUADS);
2068 glVertex2i(widget->bounds.x ,widget->bounds.y );
2069 glVertex2i(widget->bounds.x+widget->bounds.w ,widget->bounds.y );
2070 glVertex2i(widget->bounds.x+widget->bounds.w ,widget->bounds.y+widget->bounds.h );
2071 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
2072 glEnd();
2073 }
2074 set_alphacolor(blackRGBA);
2075 glBegin(GL_TRIANGLES);
2076 glVertex2i(wid_info->button->bounds.x ,wid_info->button->bounds.y);
2077 glVertex2i(wid_info->button->bounds.x ,wid_info->button->bounds.y + wid_info->button->bounds.h);
2078 glVertex2i(wid_info->button->bounds.x +wid_info->button->bounds.w ,wid_info->button->bounds.y + wid_info->button->bounds.h);
2079 glEnd();
2080 }
2081
action_ColorChooserWidget(void * data)2082 static void action_ColorChooserWidget(void *data)
2083 {
2084 ColorChooserWidget *wid_info;
2085 GLWidget *widget;
2086
2087 if (!(widget = (GLWidget *)data)) {
2088 error("action_ColorChooserWidget: argument is NULL!");
2089 return;
2090 }
2091
2092 if (widget->WIDGET != COLORCHOOSERWIDGET) {
2093 error("action_ColorChooserWidget: wrong type widget!");
2094 return;
2095 }
2096
2097 wid_info = (ColorChooserWidget *)(widget->wid_info);
2098
2099 if (!wid_info) {
2100 error("action_ColorChooserWidget: wid_info missing");
2101 return;
2102 }
2103
2104 if (wid_info->expanded) {
2105 if (wid_info->mod) {
2106 DelGLWidgetListItem(&(widget->children),wid_info->mod);
2107 widget->bounds.h -= wid_info->mod->bounds.h;
2108 Close_Widget(&(wid_info->mod));
2109 } else error("action_ColorChooserWidget: Color mod widget mysteriously missing!");
2110 wid_info->expanded = false;
2111 } else {
2112 if (!(wid_info->mod)) {
2113 wid_info->mod = Init_ColorModWidget(wid_info->value,wid_info->fgcolor,&nullRGBA,wid_info->callback,wid_info->data);
2114 if (!(wid_info->mod)) {
2115 error("action_ColorChooserWidget: Failed to Init_ColorModWidget!");
2116 }
2117 widget->bounds.h += wid_info->mod->bounds.h;
2118 AppendGLWidgetList(&(widget->children),wid_info->mod);
2119 } else error("action_ColorChooserWidget: Color mod widget mysteriously present!");
2120 wid_info->expanded = true;
2121 }
2122
2123 confmenu_callback();
2124 }
2125
Init_ColorChooserWidget(const char * name,Uint32 * value,Uint32 * fgcolor,Uint32 * bgcolor,void (* callback)(void * tmp,const char * value),void * data)2126 GLWidget *Init_ColorChooserWidget( const char *name, Uint32 *value, Uint32 *fgcolor, Uint32 *bgcolor,
2127 void (*callback)(void *tmp, const char *value), void *data )
2128 {
2129 GLWidget *tmp;
2130 ColorChooserWidget *wid_info;
2131
2132 if (!value) {
2133 error("Faulty parameter to Init_ColorChooserWidget: value is a NULL pointer!");
2134 return NULL;
2135 }
2136 if (!(name) || !strlen(name) ) {
2137 error("name misssing for Init_ColorChooserWidget.");
2138 return NULL;
2139 }
2140
2141 tmp = Init_EmptyBaseGLWidget();
2142 if ( !tmp ) {
2143 error("Failed to malloc in Init_ColorChooserWidget.");
2144 return NULL;
2145 }
2146 tmp->wid_info = XMALLOC(ColorChooserWidget, 1);
2147 if ( !(tmp->wid_info) ) {
2148 free(tmp);
2149 error("Failed to malloc in Init_ColorChooserWidget.");
2150 return NULL;
2151 }
2152
2153 wid_info = (ColorChooserWidget *)tmp->wid_info;
2154
2155 tmp->WIDGET = COLORCHOOSERWIDGET;
2156 tmp->Draw = Paint_ColorChooserWidget;
2157 tmp->SetBounds = SetBounds_ColorChooserWidget;
2158 wid_info->value = value;
2159 wid_info->fgcolor = fgcolor;
2160 wid_info->bgcolor = bgcolor;
2161 wid_info->callback = callback;
2162 wid_info->data = data;
2163 wid_info->expanded = false;
2164 wid_info->mod = NULL;
2165
2166 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->name = Init_LabelWidget(name,fgcolor,&nullRGBA,LEFT,CENTER))) ) {
2167 Close_Widget(&tmp);
2168 error("Init_ColorChooserWidget: Failed to initialize label [%s]",name);
2169 return NULL;
2170 }
2171
2172 wid_info->name->hover = hover_optionWidget;
2173 wid_info->name->hoverdata = data;
2174
2175 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->button = Init_ButtonWidget( wid_info->value, &whiteRGBA, 1, action_ColorChooserWidget, tmp ))) ) {
2176 Close_Widget(&tmp);
2177 error("Init_ColorChooserWidget: Failed to initialize button");
2178 return NULL;
2179 }
2180
2181 tmp->bounds.w = 2 + wid_info->name->bounds.w + 5 + wid_info->button->bounds.w + 2;
2182 tmp->bounds.h = wid_info->name->bounds.h;
2183
2184 return tmp;
2185 }
2186 /***************************/
2187 /* End: ColorChooserWidget */
2188 /***************************/
2189
2190 /*****************************/
2191 /* Begin: ColorModWidget */
2192 /*****************************/
2193 static void Paint_ColorModWidget( GLWidget *widget );
2194 static void SetBounds_ColorModWidget( GLWidget *widget, SDL_Rect *b );
2195 static void Callback_ColorModWidget(void *tmp, const char *value);
2196
SetBounds_ColorModWidget(GLWidget * widget,SDL_Rect * b)2197 static void SetBounds_ColorModWidget( GLWidget *widget, SDL_Rect *b )
2198 {
2199 ColorModWidget *wi;
2200 GLWidget *tmp2;
2201 SDL_Rect b2;
2202
2203 if (!widget) return;
2204 if (!b) return;
2205 if (widget->WIDGET !=COLORMODWIDGET) {
2206 error("Wrong widget type for SetBounds_ColorModWidget [%i]",widget->WIDGET);
2207 return;
2208 }
2209
2210 if ( !(wi=((ColorModWidget *)(widget->wid_info))) ) {
2211 error("SetBounds_ColorModWidget: wid_info missing!");
2212 return;
2213 }
2214
2215 widget->bounds.x = b->x;
2216 widget->bounds.y = b->y;
2217 widget->bounds.w = b->w;
2218 widget->bounds.h = b->h;
2219
2220 tmp2 = wi->redpick;
2221
2222 b2.x = widget->bounds.x + 2;
2223 b2.y = widget->bounds.y;
2224 b2.h = tmp2->bounds.h;
2225 b2.w = tmp2->bounds.w;
2226
2227 SetBounds_GLWidget(tmp2,&b2);
2228
2229 tmp2 = wi->greenpick;
2230
2231 b2.x = widget->bounds.x + 2;
2232 b2.y += b2.h;
2233 b2.h = tmp2->bounds.h;
2234 b2.w = tmp2->bounds.w;
2235
2236 SetBounds_GLWidget(tmp2,&b2);
2237
2238 tmp2 = wi->bluepick;
2239
2240 b2.x = widget->bounds.x + 2;
2241 b2.y += b2.h;
2242 b2.h = tmp2->bounds.h;
2243 b2.w = tmp2->bounds.w;
2244
2245 SetBounds_GLWidget(tmp2,&b2);
2246
2247 tmp2 = wi->alphapick;
2248
2249 b2.x = widget->bounds.x + 2;
2250 b2.y += b2.h;
2251 b2.h = tmp2->bounds.h;
2252 b2.w = tmp2->bounds.w;
2253
2254 SetBounds_GLWidget(tmp2,&b2);
2255 }
2256
Paint_ColorModWidget(GLWidget * widget)2257 static void Paint_ColorModWidget( GLWidget *widget )
2258 {
2259 ColorModWidget *wid_info;
2260 SDL_Rect b;
2261
2262 if (!widget) {
2263 error("Paint_ColorModWidget: argument is NULL!");
2264 return;
2265 }
2266
2267 if ( widget->WIDGET != COLORMODWIDGET ) {
2268 error("Paint_ColorModWidget: widget is not a ColorModWidget!");
2269 return;
2270 }
2271
2272 wid_info = (ColorModWidget *)(widget->wid_info);
2273
2274 if (!wid_info) {
2275 error("Paint_ColorModWidget: wid_info missing");
2276 return;
2277 }
2278
2279 if ( (wid_info->bgcolor) && *(wid_info->bgcolor) ) {
2280 b.x = widget->bounds.x;
2281 b.y = widget->bounds.y;
2282 b.w = widget->bounds.w;
2283 b.h = widget->bounds.h;
2284 set_alphacolor(*(wid_info->bgcolor));
2285 glBegin(GL_QUADS);
2286 glVertex2i(b.x ,b.y );
2287 glVertex2i(b.x+b.w ,b.y );
2288 glVertex2i(b.x+b.w ,b.y+b.h );
2289 glVertex2i(b.x ,b.y+b.h );
2290 glEnd();
2291 }
2292
2293 b.x = wid_info->redpick->bounds.x + wid_info->redpick->bounds.w + 16;
2294 b.y = widget->bounds.y + 2;
2295 b.w = widget->bounds.x + widget->bounds.w - 2 - b.x;
2296 b.h = widget->bounds.y + widget->bounds.h - 2 - b.y;
2297
2298 glBegin(GL_TRIANGLES);
2299 set_alphacolor(blackRGBA);
2300 glVertex2i(b.x ,b.y );
2301 glVertex2i(b.x ,b.y+b.h );
2302 glVertex2i(b.x+b.w ,b.y+b.h );
2303 set_alphacolor(whiteRGBA);
2304 glVertex2i(b.x ,b.y );
2305 glVertex2i(b.x+b.w ,b.y+b.h );
2306 glVertex2i(b.x+b.w ,b.y );
2307 glEnd();
2308
2309 glBegin(GL_POLYGON);
2310 set_alphacolor(whiteRGBA);
2311 glVertex2i(b.x + (GLint)(0.9*b.w) ,b.y + b.h );
2312 glVertex2i(b.x + b.w ,b.y + b.h );
2313 glVertex2i(b.x + b.w ,b.y + (GLint)(0.9*b.h) );
2314 set_alphacolor(blackRGBA);
2315 glVertex2i(b.x + (GLint)(0.1*b.w) ,b.y );
2316 glVertex2i(b.x ,b.y );
2317 glVertex2i(b.x ,b.y + (GLint)(0.1*b.h) );
2318 glEnd();
2319
2320 glBegin(GL_QUADS);
2321 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2322 set_alphacolor(*(wid_info->value));
2323 glVertex2i(b.x + (GLint)(0.1*b.w) ,b.y + (GLint)(0.1*b.h) );
2324 glVertex2i(b.x + (GLint)(0.1*b.w) ,b.y + (GLint)(0.9*b.h) );
2325 glVertex2i(b.x + (GLint)(0.9*b.w) ,b.y + (GLint)(0.9*b.h) );
2326 glVertex2i(b.x + (GLint)(0.9*b.w) ,b.y + (GLint)(0.1*b.h) );
2327 glEnd();
2328 }
2329
Callback_ColorModWidget(void * tmp,const char * value)2330 static void Callback_ColorModWidget(void *tmp, const char *value)
2331 {
2332 GLWidget *widget;
2333 ColorModWidget *wid_info;
2334 char str[10];
2335
2336 if (!(widget = (GLWidget *)tmp)) {
2337 error("Callback_ColorModWidget: argument is NULL!");
2338 return;
2339 }
2340
2341 if ( widget->WIDGET != COLORMODWIDGET ) {
2342 error("Callback_ColorModWidget: widget is not a ColorModWidget!");
2343 return;
2344 }
2345
2346 wid_info = (ColorModWidget *)(widget->wid_info);
2347
2348 if (!wid_info) {
2349 error("Callback_ColorModWidget: wid_info missing");
2350 return;
2351 }
2352
2353 *(wid_info->value) = ((wid_info->red)<<24) | ((wid_info->green)<<16)
2354 | ((wid_info->blue)<<8) | (wid_info->alpha);
2355
2356 snprintf(str,10,"#%02X%02X%02X%02X",wid_info->red,wid_info->green,wid_info->blue,wid_info->alpha);
2357 str[9] = '\0';
2358
2359 if (wid_info->callback) wid_info->callback(wid_info->data,str);
2360 }
2361
Init_ColorModWidget(Uint32 * value,Uint32 * fgcolor,Uint32 * bgcolor,void (* callback)(void * tmp,const char * value),void * data)2362 GLWidget *Init_ColorModWidget( Uint32 *value, Uint32 *fgcolor, Uint32 *bgcolor,
2363 void (*callback)(void *tmp, const char *value), void *data )
2364 {
2365 GLWidget *tmp;
2366 ColorModWidget *wid_info;
2367 int maxwidth = 0;
2368
2369 if (!value) {
2370 error("Faulty parameter to Init_ColorModWidget: value is a NULL pointer!");
2371 return NULL;
2372 }
2373 tmp = Init_EmptyBaseGLWidget();
2374 if ( !tmp ) {
2375 error("Failed to malloc in Init_ColorModWidget.");
2376 return NULL;
2377 }
2378 tmp->wid_info = XMALLOC(ColorModWidget, 1);
2379 if ( !(tmp->wid_info) ) {
2380 free(tmp);
2381 error("Failed to malloc in Init_ColorModWidget.");
2382 return NULL;
2383 }
2384
2385 wid_info = (ColorModWidget *)tmp->wid_info;
2386
2387 tmp->WIDGET = COLORMODWIDGET;
2388 tmp->Draw = Paint_ColorModWidget;
2389 tmp->SetBounds = SetBounds_ColorModWidget;
2390 wid_info->value = value;
2391 wid_info->red = ((*value) >> 24) & 255;
2392 wid_info->green = ((*value) >> 16) & 255;
2393 wid_info->blue = ((*value) >> 8) & 255;
2394 wid_info->alpha = (*value) & 255;
2395 wid_info->fgcolor = fgcolor;
2396 wid_info->bgcolor = bgcolor;
2397 wid_info->callback = callback;
2398 wid_info->data = data;
2399
2400 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->redpick = Init_IntChooserWidget("Red",&(wid_info->red),0,255,fgcolor,&nullRGBA,Callback_ColorModWidget,tmp))) ) {
2401 Close_Widget(&tmp);
2402 error("Init_ColorModWidget: Failed to initialize label [%s]","Red");
2403 return NULL;
2404 }
2405 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->greenpick = Init_IntChooserWidget("Green",&(wid_info->green),0,255,fgcolor,&nullRGBA,Callback_ColorModWidget,tmp))) ) {
2406 Close_Widget(&tmp);
2407 error("Init_ColorModWidget: Failed to initialize label [%s]","Green");
2408 return NULL;
2409 }
2410 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->bluepick = Init_IntChooserWidget("Blue",&(wid_info->blue),0,255,fgcolor,&nullRGBA,Callback_ColorModWidget,tmp))) ) {
2411 Close_Widget(&tmp);
2412 error("Init_ColorModWidget: Failed to initialize label [%s]","Blue");
2413 return NULL;
2414 }
2415 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->alphapick = Init_IntChooserWidget("Alpha",&(wid_info->alpha),0,255,fgcolor,&nullRGBA,Callback_ColorModWidget,tmp))) ) {
2416 Close_Widget(&tmp);
2417 error("Init_ColorModWidget: Failed to initialize label [%s]","Alpha");
2418 return NULL;
2419 }
2420
2421 maxwidth = MAX(maxwidth,wid_info->redpick->bounds.w);
2422 maxwidth = MAX(maxwidth,wid_info->greenpick->bounds.w);
2423 maxwidth = MAX(maxwidth,wid_info->bluepick->bounds.w);
2424 maxwidth = MAX(maxwidth,wid_info->alphapick->bounds.w);
2425
2426 wid_info->redpick->bounds.w = maxwidth;
2427 wid_info->greenpick->bounds.w = maxwidth;
2428 wid_info->bluepick->bounds.w = maxwidth;
2429 wid_info->alphapick->bounds.w = maxwidth;
2430
2431 tmp->bounds.h = wid_info->redpick->bounds.h
2432 + wid_info->greenpick->bounds.h
2433 + wid_info->bluepick->bounds.h
2434 + wid_info->alphapick->bounds.h;
2435 tmp->bounds.w = 2 + maxwidth + 16 + tmp->bounds.h + 2;
2436
2437 return tmp;
2438 }
2439 /***********************/
2440 /* End: ColorModWidget */
2441 /***********************/
2442
2443 /**********************/
2444 /* Begin: ListWidget */
2445 /**********************/
2446 static void SetBounds_ListWidget( GLWidget *widget, SDL_Rect *b );
2447 static void Paint_ListWidget( GLWidget *widget );
2448
ListWidget_Append(GLWidget * list,GLWidget * item)2449 bool ListWidget_Append( GLWidget *list, GLWidget *item )
2450 {
2451 GLWidget *curr1, **curr2;
2452 ListWidget *wid_info;
2453
2454 if (!list) {
2455 error("ListWidget_Append: *list is NULL!");
2456 return false;
2457 }
2458 if (list->WIDGET != LISTWIDGET) {
2459 error("ListWidget_Append: list is not a LISTWIDGET! [%i]",list->WIDGET);
2460 return false;
2461 }
2462 if (!(wid_info = (ListWidget *)list->wid_info)) {
2463 error("ListWidget_Append: list->wid_info missing!");
2464 return false;
2465 }
2466 if (!item) {
2467 error("ListWidget_Append: *item is NULL");
2468 return false;
2469 }
2470
2471 curr1 = item;
2472 while (curr1) {
2473 curr2 = &(list->children);
2474 while (*curr2) {
2475 if (*curr2 == curr1) break;
2476 curr2 = &((*curr2)->next);
2477 }
2478
2479 if (*curr2) {
2480 error("ListWidget_Append: Attempt to append an existing item!");
2481 break;
2482 }
2483
2484 *curr2 = curr1;
2485 curr1 = curr1->next;
2486 /* disengage added item from the item list t be added */
2487 (*curr2)->next = NULL;
2488
2489 ++wid_info->num_elements;
2490 }
2491
2492 /* This works since SetBounds_ListWidget copies the content
2493 * if the SDL_Rect *
2494 */
2495 SetBounds_ListWidget( list, &(list->bounds));
2496
2497 return true;
2498 }
2499
ListWidget_Prepend(GLWidget * list,GLWidget * item)2500 bool ListWidget_Prepend( GLWidget *list, GLWidget *item )
2501 {
2502 GLWidget *curr1, *curr2, **entry_pt, *first;
2503 ListWidget *wid_info;
2504 /*int y_rel;*/
2505
2506 if (!list) {
2507 error("ListWidget_Prepend: *list is NULL!");
2508 return false;
2509 }
2510 if (list->WIDGET != LISTWIDGET) {
2511 error("ListWidget_Prepend: list is not a LISTWIDGET! [%i]",list->WIDGET);
2512 return false;
2513 }
2514 if (!(wid_info = (ListWidget *)list->wid_info)) {
2515 error("ListWidget_Prepend: list->wid_info missing!");
2516 return false;
2517 }
2518 if (!item) {
2519 error("ListWidget_Prepend: *item is NULL");
2520 return false;
2521 }
2522
2523 entry_pt = &(list->children);
2524 first = *entry_pt;
2525
2526 curr1 = item;
2527 while (curr1) {
2528 curr2 = list->children;
2529 while (curr2) {
2530 if (curr2 == item) break;
2531 curr2 = curr2->next;
2532 }
2533
2534 if (curr2) {
2535 error("ListWidget_Append: Attempt to append an existing item!");
2536 break;
2537 }
2538
2539 *entry_pt = curr1;
2540 curr1 = curr1->next;
2541 (*entry_pt)->next = first;
2542 entry_pt = &((*entry_pt)->next);
2543
2544 ++wid_info->num_elements;
2545 }
2546
2547 /* This works since SetBounds_ListWidget copies the content
2548 * if the SDL_Rect *
2549 */
2550 SetBounds_ListWidget( list, &(list->bounds));
2551
2552 return true;
2553 }
2554
ListWidget_Insert(GLWidget * list,GLWidget * target,GLWidget * item)2555 bool ListWidget_Insert( GLWidget *list, GLWidget *target, GLWidget *item )
2556 {
2557 GLWidget **curr, *curr1, *curr2;
2558 ListWidget *wid_info;
2559
2560 if (!list) {
2561 error("ListWidget_Insert: *list is NULL!");
2562 return false;
2563 }
2564 if (list->WIDGET != LISTWIDGET) {
2565 error("ListWidget_Insert: list is not a LISTWIDGET! [%i]",list->WIDGET);
2566 return false;
2567 }
2568 if (!(wid_info = (ListWidget *)list->wid_info)) {
2569 error("ListWidget_Insert: list->wid_info missing!");
2570 return false;
2571 }
2572 if (!item) {
2573 error("ListWidget_Insert: *item is NULL");
2574 return false;
2575 }
2576
2577 curr = &(list->children);
2578 while (*curr) {
2579 if (*curr == target) break;
2580 curr = &((*curr)->next);
2581 }
2582
2583 if (!(*curr)) {
2584 error("ListWidget_Insert: target is not in the list!");
2585 return false;
2586 }
2587
2588 curr1 = item;
2589 while (curr1) {
2590 curr2 = list->children;
2591 while (curr2) {
2592 if (curr2 == item) break;
2593 curr2 = curr2->next;
2594 }
2595
2596 if (curr2) {
2597 error("ListWidget_Append: Attempt to append an existing item!");
2598 break;
2599 }
2600
2601 *curr = curr1;
2602 curr1 = curr1->next;
2603 (*curr)->next = target;
2604 curr = &((*curr)->next);
2605
2606 ++wid_info->num_elements;
2607 }
2608
2609 /* This works since SetBounds_ListWidget copies the content
2610 * if the SDL_Rect *
2611 */
2612 SetBounds_ListWidget( list, &(list->bounds));
2613
2614 return true;
2615 }
2616
ListWidget_Remove(GLWidget * list,GLWidget * item)2617 bool ListWidget_Remove( GLWidget *list, GLWidget *item )
2618 {
2619 GLWidget **curr;
2620 ListWidget *wid_info;
2621
2622 if (!list) {
2623 error("ListWidget_Remove: *list is NULL!");
2624 return false;
2625 }
2626 if (list->WIDGET != LISTWIDGET) {
2627 error("ListWidget_Remove: list is not a LISTWIDGET! [%i]",list->WIDGET);
2628 return false;
2629 }
2630 if (!(wid_info = (ListWidget *)list->wid_info)) {
2631 error("ListWidget_Remove: list->wid_info missing!");
2632 return false;
2633 }
2634 if (!item) {
2635 error("ListWidget_Remove: *item is NULL");
2636 return false;
2637 }
2638
2639 curr = &(list->children);
2640 while (*curr) {
2641 if (*curr == item) {
2642 break;
2643 }
2644 curr = &((*curr)->next);
2645 }
2646
2647 if (!(*curr)) {
2648 error("ListWidget_Remove: item is not in the list!");
2649 return false;
2650 }
2651
2652 *curr = (*curr)->next;
2653 item->next = NULL;
2654
2655 --wid_info->num_elements;
2656
2657 /* This works since SetBounds_ListWidget copies the content
2658 * if the SDL_Rect *
2659 */
2660 SetBounds_ListWidget( list, &(list->bounds));
2661
2662 return true;
2663 }
2664
ListWidget_SetScrollorder(GLWidget * list,bool order)2665 bool ListWidget_SetScrollorder( GLWidget *list, bool order )
2666 {
2667 /*GLWidget **curr;*/
2668 ListWidget *wid_info;
2669
2670 if (!list) {
2671 error("ListWidget_SetScrollorder: *list is NULL!");
2672 return false;
2673 }
2674 if (list->WIDGET != LISTWIDGET) {
2675 error("ListWidget_SetScrollorder: list is not a LISTWIDGET! [%i]",list->WIDGET);
2676 return false;
2677 }
2678 if (!(wid_info = (ListWidget *)list->wid_info)) {
2679 error("ListWidget_SetScrollorder: list->wid_info missing!");
2680 return false;
2681 }
2682
2683 wid_info->reverse_scroll = order;
2684
2685 /* This works since SetBounds_ListWidget copies the content
2686 * if the SDL_Rect *
2687 */
2688 SetBounds_ListWidget( list, &(list->bounds));
2689
2690 return true;
2691 }
2692
ListWidget_NELEM(GLWidget * list)2693 int ListWidget_NELEM( GLWidget *list )
2694 {
2695 ListWidget *wid_info;
2696
2697 if (!list) {
2698 error("ListWidget_NELEM: *list is NULL!");
2699 return -1;
2700 }
2701 if (list->WIDGET != LISTWIDGET) {
2702 error("ListWidget_NELEM: list is not a LISTWIDGET! [%i]",list->WIDGET);
2703 return -1;
2704 }
2705 if (!(wid_info = (ListWidget *)list->wid_info)) {
2706 error("ListWidget_Remove: list->wid_info missing!");
2707 return -1;
2708 }
2709
2710 return wid_info->num_elements;
2711 }
2712
ListWidget_GetItemByIndex(GLWidget * list,int i)2713 GLWidget *ListWidget_GetItemByIndex( GLWidget *list, int i )
2714 {
2715 GLWidget *curr;
2716 ListWidget *wid_info;
2717 int j;
2718
2719 if (!list) {
2720 error("ListWidget_NELEM: *list is NULL!");
2721 return NULL;
2722 }
2723 if (list->WIDGET != LISTWIDGET) {
2724 error("ListWidget_NELEM: list is not a LISTWIDGET! [%i]",list->WIDGET);
2725 return NULL;
2726 }
2727 if (!(wid_info = (ListWidget *)list->wid_info)) {
2728 error("ListWidget_Remove: list->wid_info missing!");
2729 return NULL;
2730 }
2731
2732 if ( i > ( wid_info->num_elements - 1) ) return NULL;
2733
2734 curr = list->children;
2735 j = 0;
2736 while (curr && (j<i)) {
2737 curr = curr->next;
2738 ++j;
2739 }
2740
2741 if ( j != i ) return NULL;
2742
2743 return curr;
2744 }
2745
2746
Paint_ListWidget(GLWidget * widget)2747 static void Paint_ListWidget( GLWidget *widget )
2748 {
2749 ListWidget *wid_info;
2750 GLWidget *curr;
2751 int count = 0;
2752 Uint32 *col;
2753
2754 if (!widget) return;
2755
2756 wid_info = (ListWidget *)(widget->wid_info);
2757
2758 glBegin(GL_QUADS);
2759
2760 curr = widget->children;
2761 while (curr) {
2762 if (count % 2) col = wid_info->bg2;
2763 else col = wid_info->bg1;
2764
2765 ++count;
2766
2767 if (*col) {
2768 set_alphacolor(*col);
2769
2770 glVertex2i(curr->bounds.x ,curr->bounds.y );
2771 glVertex2i(curr->bounds.x+widget->bounds.w ,curr->bounds.y );
2772 glVertex2i(curr->bounds.x+widget->bounds.w ,curr->bounds.y+curr->bounds.h );
2773 glVertex2i(curr->bounds.x ,curr->bounds.y+curr->bounds.h );
2774 }
2775 curr = curr->next;
2776 }
2777
2778 glEnd();
2779 }
2780
2781 /* This setbounds method has very special behaviour; basically
2782 * only one corner of the bounding box is regarded, this is
2783 * because the list is an expanding/contracting entity, and
2784 * thus the others might soon get overridden anyway.
2785 * The only way to properly bound a ListWidget is to make a
2786 * bounding widget adopt it. (i.e. a scrollpane)
2787 */
SetBounds_ListWidget(GLWidget * widget,SDL_Rect * b)2788 static void SetBounds_ListWidget( GLWidget *widget, SDL_Rect *b )
2789 {
2790 ListWidget *tmp;
2791 SDL_Rect bounds,b2;
2792 GLWidget *curr;
2793
2794 if (!widget) return;
2795 if (!b) return;
2796 if (widget->WIDGET !=LISTWIDGET) {
2797 error("Wrong widget type for SetBounds_ListWidget [%i]",widget->WIDGET);
2798 return;
2799 }
2800
2801 if (!(tmp = (ListWidget *)(widget->wid_info))) {
2802 error("SetBounds_ListWidget: wid_info missing!");
2803 return;
2804 }
2805
2806 bounds.y = b->y;
2807 bounds.x = b->x;
2808 bounds.w = 0;
2809 bounds.h = 0;
2810 curr = widget->children;
2811 while(curr) {
2812 if (tmp->direction == VERTICAL) {
2813 bounds.w = MAX(bounds.w,curr->bounds.w);
2814 bounds.h += curr->bounds.h;
2815 } else {
2816 bounds.w += curr->bounds.w;
2817 bounds.h = MAX(bounds.h,curr->bounds.h);
2818 }
2819 curr = curr->next;
2820 }
2821
2822 if (tmp->v_dir == LW_UP) {
2823 bounds.y += b->h - bounds.h;
2824 }
2825 if (tmp->v_dir == LW_VCENTER) {
2826 bounds.y += (b->h - bounds.h)/2;
2827 }
2828 if (tmp->h_dir == LW_LEFT) {
2829 bounds.x += b->w - bounds.w;
2830 }
2831 if (tmp->h_dir == LW_HCENTER) {
2832 bounds.x += (b->w - bounds.w)/2;
2833 }
2834
2835 widget->bounds.y = bounds.y;
2836 widget->bounds.h = bounds.h;
2837 widget->bounds.x = bounds.x;
2838 widget->bounds.w = bounds.w;
2839
2840 curr = widget->children;
2841 while(curr) {
2842 if (tmp->direction == VERTICAL) {
2843 bounds.h -= curr->bounds.h;
2844
2845 b2.y = bounds.y;
2846 if (tmp->reverse_scroll) {
2847 b2.y += bounds.h;
2848 } else {
2849 bounds.y += curr->bounds.h;
2850 }
2851
2852 b2.x = bounds.x;
2853 if (tmp->h_dir == LW_LEFT) {
2854 b2.x += bounds.w - curr->bounds.w;
2855 }
2856
2857 b2.h = curr->bounds.h;
2858 b2.w = widget->bounds.w;
2859 /*b2.w = curr->bounds.w;*/ /*TODO: make this optional*/
2860 } else {
2861 bounds.w -= curr->bounds.w;
2862
2863 b2.x = bounds.x;
2864 if (tmp->reverse_scroll) {
2865 b2.x += bounds.w;
2866 } else {
2867 bounds.x += curr->bounds.w;
2868 }
2869
2870 b2.y = bounds.y;
2871 if (tmp->v_dir == LW_UP) {
2872 b2.y += bounds.h - curr->bounds.h;
2873 }
2874
2875 b2.w = curr->bounds.w;
2876 b2.h = widget->bounds.h;
2877 /*b2.w = curr->bounds.w;*/ /*TODO: make this optional*/
2878 }
2879
2880 SetBounds_GLWidget( curr, &b2 );
2881
2882 curr = curr->next;
2883 }
2884 }
2885
Init_ListWidget(Uint16 x,Uint16 y,Uint32 * bg1,Uint32 * bg2,Uint32 * highlight_color,ListWidget_ver_dir_t v_dir,ListWidget_hor_dir_t h_dir,ListWidget_direction direction,bool reverse_scroll)2886 GLWidget *Init_ListWidget( Uint16 x, Uint16 y, Uint32 *bg1, Uint32 *bg2, Uint32 *highlight_color
2887 ,ListWidget_ver_dir_t v_dir, ListWidget_hor_dir_t h_dir
2888 ,ListWidget_direction direction, bool reverse_scroll )
2889 {
2890 GLWidget *tmp;
2891 ListWidget *wid_info;
2892
2893 tmp = Init_EmptyBaseGLWidget();
2894 if ( !tmp ) {
2895 error("Failed to malloc GLWidget in Init_ListWidget");
2896 return NULL;
2897 }
2898 tmp->wid_info = malloc(sizeof(ListWidget));
2899 if ( !(tmp->wid_info) ) {
2900 free(tmp);
2901 error("Failed to malloc MainWidget in Init_ListWidget");
2902 return NULL;
2903 }
2904 wid_info = ((ListWidget *)tmp->wid_info);
2905 wid_info->num_elements = 0;
2906 wid_info->bg1 = bg1;
2907 wid_info->bg2 = bg2;
2908 wid_info->highlight_color = highlight_color;
2909 wid_info->reverse_scroll = reverse_scroll;
2910 wid_info->direction = direction;
2911 wid_info->v_dir = v_dir;
2912 wid_info->h_dir = h_dir;
2913
2914 tmp->WIDGET = LISTWIDGET;
2915 tmp->bounds.x = x;
2916 tmp->bounds.y = y;
2917 tmp->bounds.w = 0;
2918 tmp->bounds.h = 0;
2919 tmp->SetBounds = SetBounds_ListWidget;
2920 tmp->Draw = Paint_ListWidget;
2921
2922 return tmp;
2923 }
2924
2925 /*******************/
2926 /* End: ListWidget */
2927 /*******************/
2928
2929 /****************************/
2930 /* Begin: ScrollPaneWidget */
2931 /****************************/
2932 static void ScrollPaneWidget_poschange( GLfloat pos , void *data );
2933 static void SetBounds_ScrollPaneWidget( GLWidget *widget, SDL_Rect *b );
2934
ScrollPaneWidget_poschange(GLfloat pos,void * data)2935 static void ScrollPaneWidget_poschange( GLfloat pos , void *data )
2936 {
2937 GLWidget *widget;
2938 GLWidget *masque;
2939 ScrollPaneWidget *wid_info;
2940 SDL_Rect bounds;
2941 GLWidget *vert_scroller;
2942 GLWidget *hori_scroller;
2943 /*GLWidget *curr;*/
2944
2945 if ( !data ) {
2946 error("NULL data to ScrollPaneWidget_poschange!");
2947 return;
2948 }
2949 widget = (GLWidget *)data;
2950 wid_info = ((ScrollPaneWidget *)(widget->wid_info));
2951 masque = wid_info->masque;
2952 if (!masque) {
2953 error("ScrollPaneWidget_poschange: masque missing!");
2954 return;
2955 }
2956 vert_scroller = wid_info->vert_scroller;
2957 hori_scroller = wid_info->hori_scroller;
2958
2959 if (wid_info->content) {
2960 bounds.x = masque->bounds.x;
2961 if (hori_scroller) {
2962 if (!hori_scroller->wid_info) {
2963 error("ScrollPaneWidget_poschange: hori_scroller wid_info missing!");
2964 return;
2965 }
2966 bounds.x -= (Sint16)((((ScrollbarWidget *)(hori_scroller->wid_info))->pos)*(wid_info->content->bounds.w));
2967 }
2968 bounds.w = wid_info->content->bounds.w;
2969 bounds.y = masque->bounds.y;
2970 if (vert_scroller) {
2971 if (!vert_scroller->wid_info) {
2972 error("ScrollPaneWidget_poschange: vert_scroller wid_info missing!");
2973 return;
2974 }
2975 bounds.y -= (Sint16)((((ScrollbarWidget *)(vert_scroller->wid_info))->pos)*(wid_info->content->bounds.h));
2976 }
2977 bounds.h = wid_info->content->bounds.h;
2978 SetBounds_GLWidget(wid_info->content,&bounds);
2979 }
2980 }
2981
SetBounds_ScrollPaneWidget(GLWidget * widget,SDL_Rect * b)2982 static void SetBounds_ScrollPaneWidget(GLWidget *widget, SDL_Rect *b )
2983 {
2984 ScrollPaneWidget *wid_info;
2985 SDL_Rect bounds;
2986 GLfloat pos;
2987 int i;
2988
2989 if (!widget) return;
2990 if (!b) return;
2991 if (widget->WIDGET != SCROLLPANEWIDGET) {
2992 error("Wrong widget type for SetBounds_ScrollPaneWidget [%i]",widget->WIDGET);
2993 return;
2994 }
2995
2996 if (!(wid_info = (ScrollPaneWidget *)(widget->wid_info))) {
2997 error("SetBounds_ScrollPaneWidget: wid_info missing!");
2998 return;
2999 }
3000
3001 widget->bounds.x = b->x;
3002 widget->bounds.w = b->w;
3003 widget->bounds.y = b->y;
3004 widget->bounds.h = b->h;
3005
3006 if (!wid_info->masque) {
3007 error("SetBounds_ScrollPaneWidget: masque missing!");
3008 return;
3009 }
3010
3011 if (!wid_info->content) {
3012 if (wid_info->vert_scroller) {
3013 Close_Widget(&(wid_info->vert_scroller));
3014 }
3015 if (wid_info->hori_scroller) {
3016 Close_Widget(&(wid_info->hori_scroller));
3017 }
3018 return;
3019 }
3020
3021 for ( i = 0 ; i < 2 ; ++i ) {
3022 if (
3023 ( (wid_info->vert_scroller) &&
3024 (widget->bounds.w - wid_info->vert_scroller->bounds.w < wid_info->content->bounds.w))
3025 || (widget->bounds.w < wid_info->content->bounds.w)
3026 ) {
3027 if (!wid_info->hori_scroller) {
3028 if ( !AppendGLWidgetList(&(widget->children),
3029 (wid_info->hori_scroller = Init_ScrollbarWidget(false,0.0f,1.0f,SB_HORISONTAL
3030 ,ScrollPaneWidget_poschange,widget)))
3031 ) {
3032 error("SetBounds_ScrollPaneWidget: Failed to init horisontal scroller!");
3033 return;
3034 }
3035 }
3036 } else {
3037 if (wid_info->hori_scroller) {
3038 Close_Widget(&(wid_info->hori_scroller));
3039 }
3040 }
3041
3042 if (
3043 ( (wid_info->hori_scroller) &&
3044 (widget->bounds.h - wid_info->hori_scroller->bounds.h < wid_info->content->bounds.h))
3045 || (widget->bounds.h < wid_info->content->bounds.h)
3046 ) {
3047 if (!wid_info->vert_scroller) {
3048 if ( !AppendGLWidgetList(&(widget->children),
3049 (wid_info->vert_scroller = Init_ScrollbarWidget(false,0.0f,1.0f,SB_VERTICAL
3050 ,ScrollPaneWidget_poschange,widget)))
3051 ) {
3052 error("SetBounds_ScrollPaneWidget: Failed to init vertical scroller!");
3053 return;
3054 }
3055 }
3056 } else {
3057 if (wid_info->vert_scroller) {
3058 Close_Widget(&(wid_info->vert_scroller));
3059 }
3060 }
3061 }
3062
3063 if (wid_info->vert_scroller) {
3064 bounds.x = widget->bounds.x + widget->bounds.w - wid_info->vert_scroller->bounds.w;
3065 bounds.w = wid_info->vert_scroller->bounds.w;
3066 bounds.y = widget->bounds.y;
3067 bounds.h = widget->bounds.h;
3068 if (wid_info->hori_scroller)
3069 bounds.h -= wid_info->hori_scroller->bounds.h;
3070
3071 SetBounds_GLWidget(wid_info->vert_scroller,&bounds);
3072 }
3073
3074 if (wid_info->hori_scroller) {
3075 bounds.x = widget->bounds.x;
3076 bounds.w = widget->bounds.w;
3077 if (wid_info->vert_scroller)
3078 bounds.w -= wid_info->vert_scroller->bounds.w;
3079 bounds.y = widget->bounds.y + widget->bounds.h - wid_info->hori_scroller->bounds.h;
3080 bounds.h = wid_info->hori_scroller->bounds.h;
3081
3082 SetBounds_GLWidget(wid_info->hori_scroller,&bounds);
3083 }
3084
3085 /* we already made sure masque exists! */
3086 bounds.x = widget->bounds.x;
3087 bounds.w = widget->bounds.w;
3088 if (wid_info->vert_scroller)
3089 bounds.w -= wid_info->vert_scroller->bounds.w;
3090 bounds.y = widget->bounds.y;
3091 bounds.h = widget->bounds.h;
3092 if (wid_info->hori_scroller)
3093 bounds.h -= wid_info->hori_scroller->bounds.h;
3094
3095 SetBounds_GLWidget(wid_info->masque,&bounds);
3096
3097 if (wid_info->content) {
3098 if (wid_info->hori_scroller) {
3099 bounds.w = wid_info->content->bounds.w;
3100 } else {
3101 bounds.w = wid_info->masque->bounds.w;
3102 }
3103 if (wid_info->vert_scroller) {
3104 bounds.h = wid_info->content->bounds.h;
3105 } else {
3106 bounds.h = wid_info->masque->bounds.h;
3107 }
3108
3109 if (wid_info->hori_scroller) {
3110 ScrollbarWidget_SetSlideSize(wid_info->hori_scroller,MIN(((GLfloat)wid_info->masque->bounds.w)/((GLfloat)bounds.w),1.0f));
3111 pos = MIN( ((ScrollbarWidget *)(wid_info->hori_scroller->wid_info))->pos, 1.0f - ((ScrollbarWidget *)(wid_info->hori_scroller->wid_info))->size);
3112 bounds.x = (Sint16)(wid_info->masque->bounds.x - pos*(wid_info->content->bounds.x));
3113 } else {
3114 bounds.x = wid_info->masque->bounds.x;
3115 }
3116
3117 if (wid_info->vert_scroller) {
3118 ScrollbarWidget_SetSlideSize(wid_info->vert_scroller,MIN(((GLfloat)wid_info->masque->bounds.h)/((GLfloat)bounds.h),1.0f));
3119 pos = MIN( ((ScrollbarWidget *)(wid_info->vert_scroller->wid_info))->pos, 1.0f - ((ScrollbarWidget *)(wid_info->vert_scroller->wid_info))->size);
3120 bounds.y = (Sint16)(wid_info->masque->bounds.y - pos*(wid_info->content->bounds.h));
3121 } else {
3122 bounds.y = wid_info->masque->bounds.y;
3123 }
3124
3125 SetBounds_GLWidget(wid_info->content,&bounds);
3126 }
3127 }
3128
Init_ScrollPaneWidget(GLWidget * content)3129 GLWidget *Init_ScrollPaneWidget( GLWidget *content )
3130 {
3131 GLWidget *tmp;
3132 ScrollPaneWidget *wid_info;
3133 /*SDL_Rect b;*/
3134
3135 tmp = Init_EmptyBaseGLWidget();
3136 if ( !tmp ) {
3137 error("Failed to malloc GLWidget in Init_ScrollPaneWidget");
3138 return NULL;
3139 }
3140 tmp->wid_info = malloc(sizeof(ScrollPaneWidget));
3141 if ( !(tmp->wid_info) ) {
3142 free(tmp);
3143 error("Failed to malloc MainWidget in Init_ScrollPaneWidget");
3144 return NULL;
3145 }
3146 wid_info = ((ScrollPaneWidget *)tmp->wid_info);
3147 wid_info->content = content;
3148 wid_info->hori_scroller = NULL;
3149 wid_info->vert_scroller = NULL;
3150
3151 tmp->WIDGET = SCROLLPANEWIDGET;
3152 tmp->bounds.x = 0;
3153 tmp->bounds.y = 0;
3154 tmp->bounds.w = 0;
3155 tmp->bounds.h = 0;
3156 tmp->SetBounds = SetBounds_ScrollPaneWidget;
3157
3158 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->masque = Init_EmptyBaseGLWidget()))
3159 ) {
3160 error("Init_ScrollPaneWidget: Failed to init masque!");
3161 Close_Widget(&tmp);
3162 return NULL;
3163 }
3164
3165 if (wid_info->content) {
3166 if ( !AppendGLWidgetList(&(wid_info->masque->children),wid_info->content) ) {
3167 error("Init_ScrollPaneWidget: Failed to adopt the content to the masque!");
3168 /*Close_Widget(&(wid_info->scroller));*/
3169 Close_Widget(&tmp);
3170 return NULL;
3171 }
3172
3173 tmp->bounds.w = wid_info->content->bounds.w;
3174 tmp->bounds.h = wid_info->content->bounds.h;
3175 }
3176
3177 /*tmp->bounds.w += wid_info->scroller->bounds.w;*/
3178
3179 return tmp;
3180 }
3181
3182 /**************************/
3183 /* End: ScrollPaneWidget */
3184 /**************************/
3185
3186 /**********************/
3187 /* Begin: MainWidget */
3188 /**********************/
3189 static void SetBounds_MainWidget( GLWidget *widget, SDL_Rect *b );
3190 static void button_MainWidget( Uint8 button, Uint8 state , Uint16 x , Uint16 y, void *data );
3191 static void Close_MainWidget( GLWidget *widget );
3192
MainWidget_ShowMenu(GLWidget * widget,bool show)3193 void MainWidget_ShowMenu( GLWidget *widget, bool show )
3194 {
3195 WrapperWidget *wid_info;
3196
3197 if (!widget) {
3198 error("MainWidget_ShowMenu: widget missing!");
3199 return;
3200 }
3201 if (widget->WIDGET != MAINWIDGET) {
3202 error("Wrong widget type for MainWidget_ShowMenu [%i]",widget->WIDGET);
3203 return;
3204 }
3205 if (!(wid_info = (WrapperWidget *)(widget->wid_info)) ) {
3206 error("MainWidget_ShowMenu: wid_info missing!");
3207 return;
3208 }
3209
3210 if (wid_info->showconf == show) return;
3211
3212 wid_info->showconf = show;
3213 if (show) {
3214 AppendGLWidgetList(&(widget->children), wid_info->confmenu);
3215 } else {
3216 DelGLWidgetListItem(&(widget->children), wid_info->confmenu);
3217 if (hovertarget)
3218 hover_optionWidget( 0, 0 , 0 , NULL );
3219 }
3220 }
3221
SetBounds_MainWidget(GLWidget * widget,SDL_Rect * b)3222 static void SetBounds_MainWidget( GLWidget *widget, SDL_Rect *b )
3223 {
3224 WrapperWidget *wid_info;
3225 SDL_Rect bs = {0,0,0,0},*bw;
3226 GLWidget *subs[5];
3227 int i,diff;
3228 bool change;
3229
3230 if (!widget) return;
3231 if (!b) return;
3232 if (widget->WIDGET != MAINWIDGET) {
3233 error("Wrong widget type for SetBounds_MainWidget [%i]",widget->WIDGET);
3234 return;
3235 }
3236
3237 if (!(wid_info = (WrapperWidget *)(widget->wid_info))) {
3238 error("SetBounds_MainWidget: wid_info missing!");
3239 return;
3240 }
3241
3242 subs[0] = wid_info->radar;
3243 subs[1] = wid_info->scorelist;
3244 subs[2] = wid_info->chat_msgs;
3245 subs[3] = wid_info->game_msgs;
3246 subs[4] = wid_info->confmenu;
3247
3248 bw = &(widget->bounds);
3249
3250 for ( i=0; i < 5 ; ++i) {
3251 if (subs[i]) {
3252 change = false;
3253
3254 bs.x = subs[i]->bounds.x;
3255 bs.w = subs[i]->bounds.w;
3256 bs.y = subs[i]->bounds.y;
3257 bs.h = subs[i]->bounds.h;
3258
3259 if ( ABS(bs.x - bw->x) > ABS( diff = (bw->x+bw->w) - (bs.x+bs.w) ) ) {
3260 bs.x = b->x + b->w - diff - bs.w;
3261 change = true;
3262 }
3263
3264 if ( ABS(bs.y - bw->y) > ABS( diff = (bw->y+bw->h) - (bs.y+bs.h) ) ) {
3265 bs.y = b->y + b->h - diff - bs.h;
3266 change = true;
3267 }
3268
3269 if ( change )
3270 SetBounds_GLWidget(subs[i],&bs);
3271 }
3272 }
3273
3274 bs.w = wid_info->alert_msgs->bounds.w;
3275 bs.x = (b->w - bs.w)/2;
3276 bs.h = wid_info->alert_msgs->bounds.h;
3277 bs.y = b->h/2 - bs.h - 50;
3278
3279 SetBounds_GLWidget(wid_info->alert_msgs,&bs);
3280
3281
3282 widget->bounds.x = b->x;
3283 widget->bounds.w = b->w;
3284 widget->bounds.y = b->y;
3285 widget->bounds.h = b->h;
3286
3287 }
3288
3289 extern int Console_isVisible(void);
3290 extern void Paste_String_to_Console(char *text);
button_MainWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)3291 static void button_MainWidget( Uint8 button, Uint8 state , Uint16 x , Uint16 y, void *data )
3292 {
3293 int scraplen;
3294
3295 if (!data) return;
3296
3297 if (state == SDL_PRESSED) {
3298 if (button == 1) {
3299 Key_press(KEY_POINTER_CONTROL);
3300 }
3301 if (button == 2) {
3302 if (Console_isVisible()) {
3303 scraptarget = NULL;
3304 get_scrap(TextScrap('T','E','X','T'), &scraplen, &scrap);
3305 if ( scraplen == 0 ) return;
3306 Paste_String_to_Console(scrap);
3307 }
3308 }
3309 }
3310 }
3311
Close_MainWidget(GLWidget * widget)3312 static void Close_MainWidget ( GLWidget *widget )
3313 {
3314 if (!widget) return;
3315 if (widget->WIDGET !=MAINWIDGET) {
3316 error("Wrong widget type for Close_MainWidget [%i]",widget->WIDGET);
3317 return;
3318 }
3319
3320 if ( scrap ) free(scrap);
3321 }
3322
Init_MainWidget(font_data * font)3323 GLWidget *Init_MainWidget( font_data *font )
3324 {
3325 GLWidget *tmp;
3326 WrapperWidget *wid_info;
3327 SDL_Rect b;
3328
3329 tmp = Init_EmptyBaseGLWidget();
3330 if ( !tmp ) {
3331 error("Failed to malloc GLWidget in Init_MainWidget");
3332 return NULL;
3333 }
3334 tmp->wid_info = malloc(sizeof(WrapperWidget));
3335 if ( !(tmp->wid_info) ) {
3336 free(tmp);
3337 error("Failed to malloc MainWidget in Init_MainWidget");
3338 return NULL;
3339 }
3340 wid_info = ((WrapperWidget *)tmp->wid_info);
3341 wid_info->font = font;
3342 wid_info->BORDER = 10;
3343 wid_info->showconf = true;
3344
3345 tmp->WIDGET = MAINWIDGET;
3346 tmp->bounds.w = draw_width;
3347 tmp->bounds.h = draw_height;
3348 tmp->SetBounds = SetBounds_MainWidget;
3349 tmp->button = button_MainWidget;
3350 tmp->buttondata = tmp;
3351 tmp->Close = Close_MainWidget;
3352
3353 if ( !AppendGLWidgetList(&(tmp->children),
3354 (wid_info->game_msgs = Init_ListWidget(wid_info->BORDER,tmp->bounds.h-wid_info->BORDER,
3355 &nullRGBA,&nullRGBA,&greenRGBA,LW_UP,LW_RIGHT,VERTICAL,true)))
3356 ) {
3357 error("Failed to initialize game msg list");
3358 Close_Widget(&tmp);
3359 return NULL;
3360 }
3361
3362 if ( !AppendGLWidgetList(&(tmp->children),
3363 (wid_info->alert_msgs = Init_ListWidget(tmp->bounds.w/2,tmp->bounds.h/2-50,
3364 &nullRGBA,&nullRGBA,&greenRGBA,LW_UP,LW_HCENTER,VERTICAL,false)))
3365 ) {
3366 error("Failed to initialize alert msg list");
3367 Close_Widget(&tmp);
3368 return NULL;
3369 }
3370
3371 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->radar = Init_RadarWidget())) ) {
3372 error("radar initialization failed");
3373 Close_Widget(&tmp);
3374 return NULL;
3375 }
3376
3377 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->scorelist = Init_ScorelistWidget())) ) {
3378 error("scorelist initialization failed");
3379 Close_Widget(&tmp);
3380 return NULL;
3381 }
3382
3383 if ( !AppendGLWidgetList(&(tmp->children),(wid_info->confmenu = Init_ConfMenuWidget(0,0))) ) {
3384 error("confmenu initialization failed");
3385 Close_Widget(&tmp);
3386 return NULL;
3387 }
3388
3389 if ( !AppendGLWidgetList(&(tmp->children),
3390 (wid_info->chat_msgs = Init_ListWidget(wid_info->radar->bounds.w + 2*wid_info->BORDER,wid_info->BORDER,
3391 &nullRGBA,&nullRGBA,&greenRGBA,LW_DOWN,LW_RIGHT,VERTICAL,false)))
3392 ) {
3393 error("Failed to initialize chat msg list");
3394 Close_Widget(&tmp);
3395 return NULL;
3396 }
3397
3398 b.w = wid_info->confmenu->bounds.w;
3399 b.h = wid_info->confmenu->bounds.h;
3400 b.x = tmp->bounds.w - b.w - 16;
3401 b.y = tmp->bounds.h - b.h - 16;
3402 SetBounds_GLWidget(wid_info->confmenu,&b);
3403
3404 return tmp;
3405 }
3406 /*******************/
3407 /* End: MainWidget */
3408 /*******************/
3409
3410 /**************************/
3411 /* Begin: ConfMenuWidget */
3412 /**************************/
3413 static Uint32 cm_name_color = 0xffff66ff;
3414 static Uint32 cm_bg1_color = 0x00000022;
3415 static Uint32 cm_bg2_color = 0xffffff22;
3416 static Uint32 cm_but1_color = 0xff000088;
3417
3418 static void Paint_ConfMenuWidget( GLWidget *widget );
3419 static void ConfMenuWidget_Quit( void *data );
3420 static void ConfMenuWidget_Save( void *data );
3421 static void ConfMenuWidget_Join( void *data );
3422 static void ConfMenuWidget_Pause( void *data );
3423 static void ConfMenuWidget_Join_Team( void *data );
3424 static void ConfMenuWidget_Config( void *data );
3425
confmenu_callback(void)3426 static void confmenu_callback( void )
3427 {
3428 GLWidget *list;
3429 WrapperWidget *mw;
3430 ConfMenuWidget *cm;
3431 ScrollPaneWidget *sp;
3432
3433 if ( !(mw = (WrapperWidget *)(MainWidget->wid_info)) ) {
3434 error("confmenu_callback: MainWidget missing!");
3435 return;
3436 }
3437 if ( !(cm = (ConfMenuWidget*)(mw->confmenu->wid_info)) ) {
3438 error("confmenu_callback: confmenu missing!");
3439 return;
3440 }
3441 if ( !(sp = (ScrollPaneWidget *)(cm->scrollpane->wid_info)) ) {
3442 error("confmenu_callback: scrollpane missing!");
3443 return;
3444 }
3445 list = sp->content;
3446 if ( !list ) {
3447 error("confmenu_callback: list missing!");
3448 return;
3449 }
3450
3451 SetBounds_GLWidget(list,&(list->bounds));
3452 SetBounds_GLWidget(mw->confmenu,&(mw->confmenu->bounds));
3453 }
3454
ConfMenuWidget_Quit(void * data)3455 static void ConfMenuWidget_Quit( void *data )
3456 {
3457 SDL_Event quit;
3458 quit.type = SDL_QUIT;
3459 SDL_PushEvent(&quit);
3460 }
3461
ConfMenuWidget_Save(void * data)3462 static void ConfMenuWidget_Save( void *data )
3463 {
3464 char path[PATH_MAX + 1];
3465
3466 Xpilotrc_get_filename(path, sizeof(path));
3467 Xpilotrc_write(path);
3468 }
3469
3470 typedef struct {
3471 GLWidget *widget;
3472 int team;
3473 } Join_Team_Data;
3474
ConfMenuWidget_Join_Team(void * data)3475 static void ConfMenuWidget_Join_Team( void *data )
3476 {
3477 char msg[16];
3478 GLWidget *widget;
3479 ConfMenuWidget *wid_info;
3480
3481 if (!(widget = ((Join_Team_Data *)data)->widget)) {
3482 error("ConfMenuWidget_Join_Team: widget missing!");
3483 return;
3484 }
3485 if ( widget->WIDGET != CONFMENUWIDGET ) {
3486 error("ConfMenuWidget_Join_Team: Wrong widget type! [%i]",widget->WIDGET);
3487 return;
3488 }
3489 if ( !(wid_info = (ConfMenuWidget *)(widget->wid_info)) ) {
3490 error("ConfMenuWidget_Join_Team: wid_info missing!");
3491 return;
3492 }
3493
3494 if (wid_info->join_list) {
3495 ListWidget_Remove(wid_info->main_list,wid_info->join_list);
3496 Close_Widget(&(wid_info->join_list));
3497 SetBounds_GLWidget(wid_info->main_list,&(wid_info->main_list->bounds));
3498 widget->bounds.x = wid_info->main_list->bounds.x - 1;
3499 widget->bounds.y = wid_info->main_list->bounds.y - 1;
3500 widget->bounds.w = wid_info->main_list->bounds.w + 2;
3501 widget->bounds.h = wid_info->main_list->bounds.h + 2;
3502 SetBounds_GLWidget(widget,&(widget->bounds));
3503 }
3504
3505 snprintf(msg, sizeof(msg), "/team %d", ((Join_Team_Data *)data)->team);
3506 Net_talk(msg);
3507
3508 Pointer_control_set_state(true);
3509 }
3510
ConfMenuWidget_Pause(void * data)3511 static void ConfMenuWidget_Pause( void *data )
3512 {
3513 GLWidget *widget;
3514 ConfMenuWidget *wid_info;
3515 bool change;
3516
3517 if (!(widget = (GLWidget *)data)) {
3518 error("ConfMenuWidget_Pause: widget missing!");
3519 return;
3520 }
3521 if ( widget->WIDGET != CONFMENUWIDGET ) {
3522 error("ConfMenuWidget_Pause: Wrong widget type! [%i]",widget->WIDGET);
3523 return;
3524 }
3525 if ( !(wid_info = (ConfMenuWidget *)(widget->wid_info)) ) {
3526 error("ConfMenuWidget_Pause: wid_info missing!");
3527 return;
3528 }
3529
3530 if (wid_info->join_list) {
3531 ListWidget_Remove(wid_info->main_list,wid_info->join_list);
3532 Close_Widget(&(wid_info->join_list));
3533 SetBounds_GLWidget(wid_info->main_list,&(wid_info->main_list->bounds));
3534 widget->bounds.x = wid_info->main_list->bounds.x - 1;
3535 widget->bounds.y = wid_info->main_list->bounds.y - 1;
3536 widget->bounds.w = wid_info->main_list->bounds.w + 2;
3537 widget->bounds.h = wid_info->main_list->bounds.h + 2;
3538 SetBounds_GLWidget(widget,&(widget->bounds));
3539 }
3540
3541 change = false;
3542 change |= Key_press(KEY_PAUSE);
3543 if (change) Net_key_change();
3544 change = false;
3545 change |= Key_release(KEY_PAUSE);
3546 if (change) Net_key_change();
3547 }
ConfMenuWidget_Join(void * data)3548 static void ConfMenuWidget_Join( void *data )
3549 {
3550 GLWidget *widget;
3551 ConfMenuWidget *wid_info;
3552 static Join_Team_Data jtd[MAX_TEAMS];
3553
3554 if (!(widget = (GLWidget *)data)) {
3555 error("ConfMenuWidget_Join: widget missing!");
3556 return;
3557 }
3558 if ( widget->WIDGET != CONFMENUWIDGET ) {
3559 error("ConfMenuWidget_Join: Wrong widget type! [%i]",widget->WIDGET);
3560 return;
3561 }
3562 if ( !(wid_info = (ConfMenuWidget *)(widget->wid_info)) ) {
3563 error("ConfMenuWidget_Join: wid_info missing!");
3564 return;
3565 }
3566
3567 if ((Setup->mode & TEAM_PLAY) == 0) {
3568 bool change = false;
3569 change |= Key_press(KEY_PAUSE);
3570 if (change) Net_key_change();
3571 change = false;
3572 change |= Key_release(KEY_PAUSE);
3573 if (change) Net_key_change();
3574 } else {
3575 int i, t;
3576 char tstr[12];
3577 bool has_base[MAX_TEAMS];
3578 GLWidget *tmp;
3579
3580 if (wid_info->join_list) {
3581 ListWidget_Remove(wid_info->main_list,wid_info->join_list);
3582 Close_Widget(&(wid_info->join_list));
3583
3584 widget->bounds.x = wid_info->main_list->bounds.x - 1;
3585 widget->bounds.y = wid_info->main_list->bounds.y - 1;
3586 widget->bounds.w = wid_info->main_list->bounds.w + 2;
3587 widget->bounds.h = wid_info->main_list->bounds.h + 2;
3588 SetBounds_GLWidget(widget,&(widget->bounds));
3589
3590 return;
3591 }
3592
3593 memset(has_base, 0, sizeof(has_base));
3594 if ((Setup->mode & TEAM_PLAY) != 0) {
3595 for (i = 0; i < num_bases; i++) {
3596 t = bases[i].team;
3597 if (t >= 0 && t < MAX_TEAMS)
3598 has_base[t] = true;
3599 }
3600 }
3601
3602 if (!(wid_info->join_list = Init_ListWidget(0,0,&cm_bg1_color,&cm_bg2_color,&nullRGBA,LW_DOWN,LW_RIGHT,VERTICAL,false))) {
3603 error("ConfMenuWidget_Join: Couldn't make the join teams list widget!");
3604 return;
3605 }
3606
3607 for (i = 0; i < MAX_TEAMS; i++) {
3608 if (has_base[i]) {
3609 snprintf(tstr, sizeof(tstr), "Join Team %i", i);
3610 jtd[i].widget = widget;
3611 jtd[i].team = i;
3612 if ( !(tmp = Init_LabelButtonWidget(tstr,&greenRGBA,&cm_bg2_color,&cm_but1_color,1,ConfMenuWidget_Join_Team,&(jtd[i]))) ) {
3613 error("ConfMenuWidget_Join: Couldn't make the join team labelButton!");
3614 return;
3615 }
3616
3617 tmp->bounds.w = widget->bounds.w - 2;
3618
3619 SetBounds_GLWidget(tmp,&(tmp->bounds));
3620
3621 ListWidget_Append(wid_info->join_list,tmp);
3622 }
3623 }
3624
3625 if (self && strchr("P", self->mychar)) {
3626 snprintf(tstr, sizeof(tstr), "Unpause");
3627 } else {
3628 snprintf(tstr, sizeof(tstr), "Pause");
3629 }
3630
3631 if ( !(tmp = Init_LabelButtonWidget(tstr,&redRGBA,&cm_bg2_color,&cm_but1_color,1,ConfMenuWidget_Pause,widget)) ) {
3632 error("ConfMenuWidget_Join: Couldn't make the Pause labelButton!");
3633 return;
3634 }
3635
3636 tmp->bounds.w = widget->bounds.w - 2;
3637
3638 SetBounds_GLWidget(tmp,&(tmp->bounds));
3639
3640 ListWidget_Append(wid_info->join_list,tmp);
3641
3642
3643 ListWidget_Append(wid_info->main_list,wid_info->join_list);
3644
3645 widget->bounds.x = wid_info->main_list->bounds.x - 1;
3646 widget->bounds.y = wid_info->main_list->bounds.y - 1;
3647 widget->bounds.w = wid_info->main_list->bounds.w + 2;
3648 widget->bounds.h = wid_info->main_list->bounds.h + 2;
3649 SetBounds_GLWidget(widget,&(widget->bounds));
3650 }
3651 }
3652
ConfMenuWidget_Config(void * data)3653 static void ConfMenuWidget_Config( void *data )
3654 {
3655 GLWidget *widget;
3656 ConfMenuWidget *wid_info;
3657
3658 if (!(widget = (GLWidget *)data)) {
3659 error("ConfMenuWidget_Close: widget missing!");
3660 return;
3661 }
3662 if ( widget->WIDGET != CONFMENUWIDGET ) {
3663 error("ConfMenuWidget_Close: Wrong widget type! [%i]",widget->WIDGET);
3664 return;
3665 }
3666 if ( !(wid_info = (ConfMenuWidget *)(widget->wid_info)) ) {
3667 error("ConfMenuWidget_Close: wid_info missing!");
3668 return;
3669 }
3670
3671 if ((wid_info->showconf = !wid_info->showconf)) {
3672 if (wid_info->join_list) {
3673 ListWidget_Remove(wid_info->main_list,wid_info->join_list);
3674 Close_Widget(&(wid_info->join_list));
3675 }
3676 ListWidget_Remove(wid_info->button_list,wid_info->jlb);
3677 ListWidget_Append(wid_info->button_list,wid_info->slb);
3678 ListWidget_Append(wid_info->main_list,wid_info->scrollpane);
3679 } else {
3680 ListWidget_Append(wid_info->button_list,wid_info->jlb);
3681 ListWidget_Remove(wid_info->button_list,wid_info->slb);
3682 ListWidget_Remove(wid_info->main_list,wid_info->scrollpane);
3683 }
3684
3685 SetBounds_GLWidget(wid_info->main_list,&(wid_info->main_list->bounds));
3686
3687 widget->bounds.x = wid_info->main_list->bounds.x - 1;
3688 widget->bounds.y = wid_info->main_list->bounds.y - 1;
3689 widget->bounds.w = wid_info->main_list->bounds.w + 2;
3690 widget->bounds.h = wid_info->main_list->bounds.h + 2;
3691 SetBounds_GLWidget(widget,&(widget->bounds));
3692 }
3693
SetBounds_ConfMenuWidget(GLWidget * widget,SDL_Rect * b)3694 static void SetBounds_ConfMenuWidget( GLWidget *widget, SDL_Rect *b )
3695 {
3696 ConfMenuWidget *wid_info;
3697 SDL_Rect bounds = {0,0,0,0};
3698
3699 if (!widget ) {
3700 error("SetBounds_ConfMenuWidget: tried to change bounds on NULL ConfMenuWidget!");
3701 return;
3702 }
3703 if ( widget->WIDGET != CONFMENUWIDGET ) {
3704 error("SetBounds_ConfMenuWidget: Wrong widget type! [%i]",widget->WIDGET);
3705 return;
3706 }
3707 if (!(wid_info = (ConfMenuWidget *)(widget->wid_info))) {
3708 error("SetBounds_ConfMenuWidget: wid_info missing!");
3709 return;
3710 }
3711 if (!b ) {
3712 error("SetBounds_ConfMenuWidget: tried to set NULL bounds on ConfMenuWidget!");
3713 return;
3714 }
3715
3716 widget->bounds.x = b->x;
3717 widget->bounds.y = b->y;
3718 widget->bounds.w = b->w;
3719 widget->bounds.h = b->h;
3720
3721 bounds.x += b->x + 1;
3722 bounds.y += b->y + 1;
3723
3724 if (!wid_info->main_list) {
3725 error("SetBounds_ConfMenuWidget: main_list missing!");
3726 return;
3727 }
3728 bounds.w = wid_info->main_list->bounds.w;
3729 bounds.h = wid_info->main_list->bounds.h;
3730
3731 SetBounds_GLWidget(wid_info->main_list,&bounds);
3732 }
3733
Paint_ConfMenuWidget(GLWidget * widget)3734 static void Paint_ConfMenuWidget( GLWidget *widget )
3735 {
3736 Uint32 edgeColor = 0xff0000ff;
3737 Uint32 bgColor = 0x0000ff88;
3738 ConfMenuWidget *wid_info;
3739
3740 if (!widget ) {
3741 error("Paint_ConfMenuWidget: tried to paint NULL ConfMenuWidget!");
3742 return;
3743 }
3744
3745 if (!(wid_info = (ConfMenuWidget *)(widget->wid_info))) {
3746 error("Paint_ConfMenuWidget: wid_info missing!");
3747 return;
3748 }
3749
3750 if ((Setup->mode & TEAM_PLAY) == 0) {
3751 if (self && strchr("P", self->mychar)) {
3752 if ( !wid_info->paused ) {
3753 ListWidget_Remove(wid_info->button_list,wid_info->jlb);
3754 Close_Widget(&(wid_info->jlb));
3755 if ( !(wid_info->jlb = Init_LabelButtonWidget("Join",&greenRGBA,&nullRGBA,&cm_but1_color,1,ConfMenuWidget_Join,widget)) ) {
3756 error("Paint_ConfMenuWidget: Couldn't make the join labelButton!");
3757 return;
3758 }
3759 SetBounds_GLWidget(wid_info->jlb, &(wid_info->clb->bounds));
3760 ListWidget_Append(wid_info->button_list,wid_info->jlb);
3761 wid_info->paused = true;
3762 }
3763 } else {
3764 if ( wid_info->paused ) {
3765 ListWidget_Remove(wid_info->button_list,wid_info->jlb);
3766 Close_Widget(&(wid_info->jlb));
3767 if ( !(wid_info->jlb = Init_LabelButtonWidget("Pause",&greenRGBA,&nullRGBA,&cm_but1_color,50,ConfMenuWidget_Pause,widget)) ) {
3768 error("Paint_ConfMenuWidget: Couldn't make the Pause labelButton!");
3769 return;
3770 }
3771 SetBounds_GLWidget(wid_info->jlb, &(wid_info->clb->bounds));
3772 ListWidget_Append(wid_info->button_list,wid_info->jlb);
3773 wid_info->paused = false;
3774 }
3775 }
3776 }
3777
3778 set_alphacolor(bgColor);
3779 glBegin(GL_QUADS);
3780 glVertex2i(widget->bounds.x ,widget->bounds.y );
3781 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y );
3782 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y+widget->bounds.h );
3783 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
3784 glEnd();
3785 glBegin(GL_LINE_LOOP);
3786 set_alphacolor(edgeColor);
3787 glVertex2i(widget->bounds.x ,widget->bounds.y );
3788 set_alphacolor(bgColor | 0x000000ff);
3789 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y );
3790 set_alphacolor(edgeColor);
3791 glVertex2i(widget->bounds.x+widget->bounds.w,widget->bounds.y+widget->bounds.h );
3792 set_alphacolor(bgColor | 0x000000ff);
3793 glVertex2i(widget->bounds.x ,widget->bounds.y+widget->bounds.h );
3794 glEnd();
3795 }
3796
Init_ConfMenuWidget(Uint16 x,Uint16 y)3797 GLWidget *Init_ConfMenuWidget( Uint16 x, Uint16 y )
3798 {
3799 GLWidget *tmp, *item, *dummy, *list;
3800 ConfMenuWidget *wid_info;
3801 int i;
3802 xp_option_t *opt;
3803
3804 tmp = Init_EmptyBaseGLWidget();
3805 if ( !tmp ) {
3806 error("Failed to malloc in Init_ConfMenu");
3807 return NULL;
3808 }
3809 tmp->wid_info = malloc(sizeof(ConfMenuWidget));
3810 if ( !(tmp->wid_info) ) {
3811 free(tmp);
3812 error("Failed to malloc in Init_ConfMenu");
3813 return NULL;
3814 }
3815 wid_info = ((ConfMenuWidget *)(tmp->wid_info));
3816
3817 tmp->WIDGET = CONFMENUWIDGET;
3818 tmp->Draw = Paint_ConfMenuWidget;
3819 tmp->SetBounds = SetBounds_ConfMenuWidget;
3820 wid_info->showconf = false;
3821 wid_info->join_list = NULL;
3822
3823 dummy = Init_EmptyBaseGLWidget();
3824 if ( !dummy ) {
3825 error("Failed to malloc in Init_ConfMenu");
3826 return NULL;
3827 }
3828
3829 for ( i=0 ; i < num_options; ++i ) {
3830 opt = Option_by_index(i);
3831 item = Init_OptionWidget(opt,&cm_name_color, &nullRGBA);
3832 if (item) {
3833 AppendGLWidgetList( &(dummy->next), item );
3834 }
3835 }
3836
3837 if (!(list = Init_ListWidget(0,0,&cm_bg1_color,&cm_bg2_color,&nullRGBA,LW_DOWN,LW_RIGHT,VERTICAL,false))) {
3838 error("Init_ConfMenuWidget: Couldn't make the list widget!");
3839 Close_WidgetTree(&dummy);
3840 Close_Widget(&tmp);
3841 return NULL;
3842 }
3843
3844 ListWidget_Append(list,dummy->next);
3845 Close_Widget(&dummy);
3846
3847 if ( !(wid_info->scrollpane = Init_ScrollPaneWidget(list)) ) {
3848 error("Init_ConfMenuWidget: Couldn't make the scrollpane!");
3849 Close_Widget(&list);
3850 Close_Widget(&tmp);
3851 return NULL;
3852 }
3853
3854 wid_info->scrollpane->bounds.h = 512;
3855
3856 if ( !(wid_info->slb = Init_LabelButtonWidget("Save",&greenRGBA,&nullRGBA,&cm_but1_color,1,ConfMenuWidget_Save,tmp)) ) {
3857 error("Init_ConfMenuWidget: Couldn't make the save labelButton!");
3858 Close_Widget(&tmp);
3859 return NULL;
3860 }
3861
3862 if (self && strchr("P", self->mychar))
3863 wid_info->paused = true;
3864 else
3865 wid_info->paused = false;
3866
3867 if ((Setup->mode & TEAM_PLAY) || wid_info->paused) {
3868 if ( !(wid_info->jlb = Init_LabelButtonWidget("Join",&greenRGBA,&nullRGBA,&cm_but1_color,1,ConfMenuWidget_Join,tmp)) ) {
3869 error("Init_ConfMenuWidget: Couldn't make the join labelButton!");
3870 Close_Widget(&tmp);
3871 return NULL;
3872 }
3873 } else {
3874 if ( !(wid_info->jlb = Init_LabelButtonWidget("Pause",&greenRGBA,&nullRGBA,&cm_but1_color,50,ConfMenuWidget_Pause,tmp)) ) {
3875 error("Init_ConfMenuWidget: Couldn't make the Pause labelButton!");
3876 Close_Widget(&tmp);
3877 return NULL;
3878 }
3879 }
3880
3881 if ( !(wid_info->clb = Init_LabelButtonWidget("Config",&yellowRGBA,&nullRGBA,&cm_but1_color,1,ConfMenuWidget_Config,tmp)) ) {
3882 error("Init_ConfMenuWidget: Couldn't make the config labelButton!");
3883 Close_Widget(&tmp);
3884 return NULL;
3885 }
3886
3887 if ( !(wid_info->qlb = Init_LabelButtonWidget("Quit",&redRGBA,&nullRGBA,&cm_but1_color,1,ConfMenuWidget_Quit,tmp)) ) {
3888 error("Init_ConfMenuWidget: Couldn't make the quit label!");
3889 Close_Widget(&tmp);
3890 return NULL;
3891 }
3892
3893 if (!(wid_info->button_list = Init_ListWidget(0,0,&nullRGBA,&nullRGBA,&nullRGBA,LW_DOWN,LW_RIGHT,HORISONTAL,true))) {
3894 error("Init_ConfMenuWidget: Couldn't make the button_list widget!");
3895 Close_Widget(&tmp);
3896 return NULL;
3897 }
3898
3899 wid_info->clb->bounds.w = ( wid_info->scrollpane->bounds.w + 10 )/3 + 1;
3900 SetBounds_GLWidget(wid_info->clb, &(wid_info->clb->bounds));
3901 SetBounds_GLWidget(wid_info->slb, &(wid_info->clb->bounds));
3902 SetBounds_GLWidget(wid_info->jlb, &(wid_info->clb->bounds));
3903 SetBounds_GLWidget(wid_info->qlb, &(wid_info->clb->bounds));
3904
3905
3906 ListWidget_Append(wid_info->button_list,wid_info->qlb);
3907 ListWidget_Append(wid_info->button_list,wid_info->clb);
3908 ListWidget_Append(wid_info->button_list,wid_info->jlb);
3909
3910 if (!(wid_info->main_list = Init_ListWidget(0,0,&nullRGBA,&nullRGBA,&nullRGBA,LW_UP,LW_LEFT,VERTICAL,true))) {
3911 error("Init_ConfMenuWidget: Couldn't make the main_list widget!");
3912 Close_Widget(&tmp);
3913 return NULL;
3914 }
3915
3916 ListWidget_Append(wid_info->main_list,wid_info->button_list);
3917
3918 if (!AppendGLWidgetList( &(tmp->children), wid_info->main_list )) {
3919 error("Init_ConfMenuWidget: failed to append main_list to children");
3920 Close_Widget(&tmp);
3921 return NULL;
3922 }
3923
3924 tmp->bounds.x = x;
3925 tmp->bounds.y = y;
3926 tmp->bounds.w = wid_info->main_list->bounds.w + 2;
3927 tmp->bounds.h = wid_info->main_list->bounds.h + 2;
3928
3929 SetBounds_GLWidget(tmp,&(tmp->bounds));
3930
3931 return tmp;
3932 }
3933 /***********************/
3934 /* End: ConfMenuWidget */
3935 /***********************/
3936
3937 /****************************/
3938 /* Begin: ImageButtonWidget */
3939 /****************************/
3940
Button_ImageButtonWidget(Uint8 button,Uint8 state,Uint16 x,Uint16 y,void * data)3941 static void Button_ImageButtonWidget(Uint8 button, Uint8 state, Uint16 x,
3942 Uint16 y, void *data)
3943 {
3944 GLWidget *widget;
3945 ImageButtonWidget *info;
3946
3947 widget = (GLWidget*)data;
3948 if (widget->WIDGET != IMAGEBUTTONWIDGET) {
3949 error("expected IMAGEBUTTONWIDGET got [%d]", widget->WIDGET);
3950 return;
3951 }
3952 info = (ImageButtonWidget*)widget->wid_info;
3953 if (info->state == state) return;
3954 info->state = state;
3955
3956 if (state != SDL_PRESSED && info->onClick) {
3957 if (x >= widget->bounds.x
3958 && x <= widget->bounds.x + widget->bounds.w
3959 && y >= widget->bounds.y
3960 && y <= widget->bounds.y + widget->bounds.h)
3961 info->onClick(widget);
3962 }
3963 }
3964
Close_ImageButtonWidget(GLWidget * widget)3965 static void Close_ImageButtonWidget(GLWidget *widget)
3966 {
3967 ImageButtonWidget *info;
3968 if (!widget) return;
3969 if (widget->WIDGET != IMAGEBUTTONWIDGET) {
3970 error("Wrong widget type for Close_ImageButtonWidget [%i]",
3971 widget->WIDGET);
3972 return;
3973 }
3974 info = (ImageButtonWidget*)widget->wid_info;
3975 free_string_texture(&(info->tex));
3976 if (info->imageUp) glDeleteTextures(1, &(info->imageUp));
3977 if (info->imageDown) glDeleteTextures(1, &(info->imageDown));
3978 }
3979
Paint_ImageButtonWidget(GLWidget * widget)3980 static void Paint_ImageButtonWidget(GLWidget *widget)
3981 {
3982 SDL_Rect *b;
3983 ImageButtonWidget *info;
3984 int x, y, c;
3985
3986 if (!widget) return;
3987
3988 b = &(widget->bounds);
3989 info = (ImageButtonWidget*)(widget->wid_info);
3990
3991 if (info->state != SDL_PRESSED) {
3992 if (info->imageUp) {
3993 set_alphacolor(info->bg);
3994 glBindTexture(GL_TEXTURE_2D, info->imageUp);
3995 glEnable(GL_TEXTURE_2D);
3996 glBegin(GL_QUADS);
3997 glTexCoord2f(info->txcUp.MinX, info->txcUp.MinY);
3998 glVertex2i(b->x, b->y);
3999 glTexCoord2f(info->txcUp.MaxX, info->txcUp.MinY);
4000 glVertex2i(b->x + b->w , b->y);
4001 glTexCoord2f(info->txcUp.MaxX, info->txcUp.MaxY);
4002 glVertex2i(b->x + b->w , b->y + b->h);
4003 glTexCoord2f(info->txcUp.MinY, info->txcUp.MaxY);
4004 glVertex2i(b->x, b->y + b->h);
4005 glEnd();
4006 }
4007 } else {
4008 if (info->imageDown) {
4009 set_alphacolor(info->bg);
4010 glBindTexture(GL_TEXTURE_2D, info->imageDown);
4011 glEnable(GL_TEXTURE_2D);
4012 glBegin(GL_QUADS);
4013 glTexCoord2f(info->txcDown.MinX, info->txcDown.MinY);
4014 glVertex2i(b->x, b->y);
4015 glTexCoord2f(info->txcDown.MaxX, info->txcDown.MinY);
4016 glVertex2i(b->x + b->w , b->y);
4017 glTexCoord2f(info->txcDown.MaxX, info->txcDown.MaxY);
4018 glVertex2i(b->x + b->w , b->y + b->h);
4019 glTexCoord2f(info->txcDown.MinY, info->txcDown.MaxY);
4020 glVertex2i(b->x, b->y + b->h);
4021 glEnd();
4022 }
4023 }
4024
4025 x = widget->bounds.x + widget->bounds.w / 2;
4026 y = widget->bounds.y + widget->bounds.h / 2;
4027 c = (int)(info->fg ? info->fg : whiteRGBA);
4028 if (info->state == SDL_PRESSED) {
4029 x += 1;
4030 y += 1;
4031 }
4032 disp_text(&(info->tex), c,
4033 CENTER, CENTER,
4034 x, draw_height - y,
4035 true);
4036 }
4037
Init_ImageButtonWidget(const char * text,const char * upImage,const char * downImage,Uint32 bg,Uint32 fg,void (* onClick)(GLWidget * widget))4038 GLWidget *Init_ImageButtonWidget(const char *text,
4039 const char *upImage,
4040 const char *downImage,
4041 Uint32 bg,
4042 Uint32 fg,
4043 void (*onClick)(GLWidget *widget))
4044 {
4045 GLWidget *tmp;
4046 ImageButtonWidget *info;
4047 SDL_Surface *surface;
4048 char imagePath[256];
4049 int width, height;
4050
4051 if (!text) {
4052 error("text missing for Init_ImageButtonWidget.");
4053 return NULL;
4054 }
4055 tmp = Init_EmptyBaseGLWidget();
4056 if ( !tmp ) {
4057 error("Failed to malloc in Init_ImageButtonWidget");
4058 return NULL;
4059 }
4060 info = XMALLOC(ImageButtonWidget, 1);
4061 if (!info) {
4062 free(tmp);
4063 error("Failed to malloc in Init_ImageButtonWidget");
4064 return NULL;
4065 }
4066
4067 info->onClick = onClick;
4068 info->fg = fg;
4069 info->bg = bg;
4070 info->state = SDL_RELEASED;
4071 info->imageUp = 0;
4072 info->imageDown = 0;
4073
4074 if (!render_text(&gamefont, text, &(info->tex))) {
4075 free(info);
4076 free(tmp);
4077 error("Failed to render text in Init_ImageButtonWidget");
4078 return NULL;
4079 }
4080 width = info->tex.width + 1;
4081 height = info->tex.height + 1;
4082
4083 #ifdef HAVE_SDL_IMAGE
4084 sprintf(imagePath, "%s%s", CONF_TEXTUREDIR, upImage);
4085 surface = IMG_Load(imagePath);
4086 if (surface) {
4087 info->imageUp = SDL_GL_LoadTexture(surface, &(info->txcUp));
4088 if (width < surface->w) width = surface->w;
4089 if (height < surface->h) height = surface->h;
4090 SDL_FreeSurface(surface);
4091 } else {
4092 error("Failed to load button image %s", imagePath);
4093 }
4094 sprintf(imagePath, "%s%s", CONF_TEXTUREDIR, downImage);
4095 surface = IMG_Load(imagePath);
4096 if (surface) {
4097 info->imageDown = SDL_GL_LoadTexture(surface, &(info->txcDown));
4098 if (width < surface->w) width = surface->w;
4099 if (height < surface->h) height = surface->h;
4100 SDL_FreeSurface(surface);
4101 } else {
4102 error("Failed to load button image %s", imagePath);
4103 }
4104 #endif
4105
4106 tmp->WIDGET = IMAGEBUTTONWIDGET;
4107 tmp->wid_info = info;
4108 tmp->bounds.w = width;
4109 tmp->bounds.h = height;
4110 tmp->Draw = Paint_ImageButtonWidget;
4111 tmp->Close = Close_ImageButtonWidget;
4112 tmp->button = Button_ImageButtonWidget;
4113 tmp->buttondata = tmp;
4114 return tmp;
4115 }
4116 /**************************/
4117 /* End: ImageButtonWidget */
4118 /**************************/
4119
4120 /*****************************/
4121 /* Begin: LabelButtonWidget */
4122 /*****************************/
4123 static void SetBounds_LabelButtonWidget( GLWidget *widget, SDL_Rect *b );
4124
SetBounds_LabelButtonWidget(GLWidget * widget,SDL_Rect * b)4125 static void SetBounds_LabelButtonWidget( GLWidget *widget, SDL_Rect *b )
4126 {
4127 LabelButtonWidget *wid_info;
4128
4129 if (!widget ) {
4130 error("SetBounds_LabelButtonWidget: tried to change bounds on NULL ImageButtonWidget!");
4131 return;
4132 }
4133 if ( widget->WIDGET != LABELBUTTONWIDGET ) {
4134 error("SetBounds_LabelButtonWidget: Wrong widget type! [%i]",widget->WIDGET);
4135 return;
4136 }
4137 if (!(wid_info = (LabelButtonWidget *)(widget->wid_info))) {
4138 error("SetBounds_LabelButtonWidget: wid_info missing!");
4139 return;
4140 }
4141 if (!b ) {
4142 error("SetBounds_LabelButtonWidget: tried to set NULL bounds on LabelButtonWidget!");
4143 return;
4144 }
4145
4146 widget->bounds.x = b->x;
4147 widget->bounds.w = b->w;
4148 widget->bounds.y = b->y;
4149 widget->bounds.h = b->h;
4150
4151 SetBounds_GLWidget(wid_info->label,&(widget->bounds));
4152 SetBounds_GLWidget(wid_info->button,&(widget->bounds));
4153 }
4154
Init_LabelButtonWidget(const char * text,Uint32 * text_color,Uint32 * bg_color,Uint32 * active_color,Uint8 depress_time,void (* action)(void * data),void * actiondata)4155 GLWidget *Init_LabelButtonWidget( const char *text,
4156 Uint32 *text_color,
4157 Uint32 *bg_color,
4158 Uint32 *active_color,
4159 Uint8 depress_time,
4160 void (*action)(void *data),
4161 void *actiondata)
4162 {
4163 GLWidget *widget;
4164 LabelButtonWidget *wid_info;
4165
4166 widget = Init_EmptyBaseGLWidget();
4167 if ( !widget ) {
4168 error("Failed to malloc in Init_LabelButtonWidget");
4169 return NULL;
4170 }
4171 widget->wid_info = malloc(sizeof(LabelButtonWidget));
4172 if ( !(widget->wid_info) ) {
4173 free(widget);
4174 error("Failed to malloc in Init_LabelButtonWidget");
4175 return NULL;
4176 }
4177 wid_info = ((LabelButtonWidget *)(widget->wid_info));
4178
4179 widget->WIDGET = LABELBUTTONWIDGET;
4180 widget->SetBounds = SetBounds_LabelButtonWidget;
4181
4182 wid_info->label = Init_LabelWidget( text , text_color, &nullRGBA, CENTER, CENTER );
4183
4184 if (!AppendGLWidgetList(&(widget->children),wid_info->label)) {
4185 error("Init_LabelButtonWidget: Could not initialize label widget!");
4186 Close_Widget(&widget);
4187 return NULL;
4188 }
4189
4190 wid_info->button = Init_ButtonWidget( bg_color, active_color, depress_time, action, actiondata);
4191
4192 if (!AppendGLWidgetList(&(widget->children),wid_info->button)) {
4193 error("Init_LabelButtonWidget: Could not initialize button widget!");
4194 Close_Widget(&widget);
4195 return NULL;
4196 }
4197
4198 SetBounds_GLWidget(widget,&(wid_info->label->bounds));
4199
4200 return widget;
4201 }
4202 /**************************/
4203 /* End: LabelButtonWidget */
4204 /**************************/
4205