Freeciv-3.2
Loading...
Searching...
No Matches
widget_scrollbar.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2006 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* SDL2 */
19#ifdef SDL2_PLAIN_INCLUDE
20#include <SDL.h>
21#else /* SDL2_PLAIN_INCLUDE */
22#include <SDL2/SDL.h>
23#endif /* SDL2_PLAIN_INCLUDE */
24
25/* utility */
26#include "log.h"
27
28/* gui-sdl2 */
29#include "colors.h"
30#include "graphics.h"
31#include "gui_id.h"
32#include "gui_tilespec.h"
33#include "mapview.h"
34#include "themespec.h"
35
36#include "widget.h"
37#include "widget_p.h"
38
39struct UP_DOWN {
40 struct widget *begin;
41 struct widget *end;
45 float old_y;
46 int step;
47 int prev_x;
48 int prev_y;
49 int offset; /* number of pixels the mouse is away from the slider origin */
50};
51
52#define widget_add_next(new_widget, add_dock) \
53do { \
54 new_widget->prev = add_dock; \
55 new_widget->next = add_dock->next; \
56 if (add_dock->next) { \
57 add_dock->next->prev = new_widget; \
58 } \
59 add_dock->next = new_widget; \
60} while (FALSE)
61
62static int (*baseclass_redraw)(struct widget *pwidget);
63
64/* =================================================== */
65/* ===================== VSCROLLBAR ================== */
66/* =================================================== */
67
68/**********************************************************************/
75 enum widget_state state,
77{
79 SDL_Rect src, des;
80 Uint16 i;
85
86 tile_len_end = vert_theme->h / 16;
87
88 start_y = 0 + state * (vert_theme->h / 4);
89
91
93
94 /* Correction */
97 }
98
99 if (!tile_count_midd) {
101 } else {
103 }
104
105 src.x = 0;
106 src.y = start_y;
107 src.w = vert_theme->w;
108 src.h = tile_len_end;
109 alphablit(vert_theme, &src, versurf, NULL, 255);
110
111 src.y = start_y + tile_len_end;
112 src.h = tile_len_midd;
113
114 des.x = 0;
115
116 for (i = 0; i < tile_count_midd; i++) {
118 alphablit(vert_theme, &src, versurf, &des, 255);
119 }
120
122 src.h = tile_len_end;
123 des.y = versurf->h - tile_len_end;
124 alphablit(vert_theme, &src, versurf, &des, 255);
125
126 return versurf;
127}
128
129/**********************************************************************/
132static int redraw_vert(struct widget *vert)
133{
134 int ret;
136
137 ret = (*baseclass_redraw)(vert);
138 if (ret != 0) {
139 return ret;
140 }
141
144 vert->size.h);
145 ret = blit_entire_src(vert_surf, vert->dst->surface,
146 vert->size.x, vert->size.y);
147
149
150 return ret;
151}
152
153/**********************************************************************/
165 Uint16 height, Uint32 flags)
166{
167 struct widget *vert = widget_new();
168
169 vert->theme = vert_theme;
170 vert->size.w = vert_theme->w;
171 vert->size.h = height;
175 vert->mod = KMOD_NONE;
176 vert->dst = pdest;
177
178 baseclass_redraw = vert->redraw;
179 vert->redraw = redraw_vert;
180
181 return vert;
182}
183
184/**********************************************************************/
188{
189 vert->size.x = x;
190 vert->size.y = y;
191 vert->gfx = crop_rect_from_surface(vert->dst->surface, &vert->size);
192
193 return redraw_vert(vert);
194}
195
196/* =================================================== */
197/* ===================== HSCROLLBAR ================== */
198/* =================================================== */
199
200/**********************************************************************/
207 enum widget_state state,
209{
211 SDL_Rect src, des;
212 Uint16 i;
213 Uint16 start_x;
217
218 tile_len_end = horiz_theme->w / 16;
219
220 start_x = 0 + state * (horiz_theme->w / 4);
221
223
225
226 /* Correction */
229 }
230
231 if (!tile_count_midd) {
233 } else {
235 }
236
237 src.y = 0;
238 src.x = start_x;
239 src.h = horiz_theme->h;
240 src.w = tile_len_end;
241 alphablit(horiz_theme, &src, horsurf, NULL, 255);
242
243 src.x = start_x + tile_len_end;
244 src.w = tile_len_midd;
245
246 des.y = 0;
247
248 for (i = 0; i < tile_count_midd; i++) {
250 alphablit(horiz_theme, &src, horsurf, &des, 255);
251 }
252
253 src.x = start_x + tile_len_end + tile_len_midd;
254 src.w = tile_len_end;
255 des.x = horsurf->w - tile_len_end;
256 alphablit(horiz_theme, &src, horsurf, &des, 255);
257
258 return horsurf;
259}
260
261/**********************************************************************/
264static int redraw_horiz(struct widget *horiz)
265{
266 int ret;
268
269 ret = (*baseclass_redraw)(horiz);
270 if (ret != 0) {
271 return ret;
272 }
273
275 get_wstate(horiz),
276 horiz->size.w);
278 horiz->size.x, horiz->size.y);
279
281
282 return ret;
283}
284
285/**********************************************************************/
297 struct gui_layer *pdest,
298 Uint16 width, Uint32 flags)
299{
300 struct widget *hor = widget_new();
301
302 hor->theme = horiz_theme;
303 hor->size.w = width;
304 hor->size.h = horiz_theme->h;
305 set_wflag(hor, WF_FREE_STRING | flags);
308 hor->mod = KMOD_NONE;
309 hor->dst = pdest;
310
311 baseclass_redraw = hor->redraw;
312 hor->redraw = redraw_horiz;
313
314 return hor;
315}
316
317/**********************************************************************/
320int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
321{
322 horiz->size.x = x;
323 horiz->size.y = y;
324 horiz->gfx = crop_rect_from_surface(horiz->dst->surface, &horiz->size);
325
326 return redraw_horiz(horiz);
327}
328
329/* =================================================== */
330/* ===================== ================== */
331/* =================================================== */
332
333/**********************************************************************/
336static int get_step(struct scroll_bar *scroll)
337{
338 float step = scroll->max - scroll->min;
339
340 step *= (float) (1.0 - (float) (scroll->active * scroll->step) /
341 (float)scroll->count);
342 step /= (float)(scroll->count - scroll->active * scroll->step);
343 step *= (float)scroll->step;
344 step++;
345
346 return (int)step;
347}
348
349/**********************************************************************/
352static int get_position(struct advanced_dialog *dlg)
353{
354 struct widget *buf = dlg->active_widget_list;
355 int count = dlg->scroll->active * dlg->scroll->step - 1;
356 int step = get_step(dlg->scroll);
357
358 /* find last seen widget */
359 while (count) {
360 if (buf == dlg->begin_active_widget_list) {
361 break;
362 }
363 count--;
364 buf = buf->prev;
365 }
366
367 count = 0;
368 if (buf != dlg->begin_active_widget_list) {
369 do {
370 count++;
371 buf = buf->prev;
372 } while (buf != dlg->begin_active_widget_list);
373 }
374
375 if (dlg->scroll->pscroll_bar) {
376 return dlg->scroll->max - dlg->scroll->pscroll_bar->size.h -
377 count * (float)step / dlg->scroll->step;
378 } else {
379 return dlg->scroll->max - count * (float)step / dlg->scroll->step;
380 }
381}
382
383/**************************************************************************
384 Vertical scroll_bar
385**************************************************************************/
386
387static struct widget *up_scroll_widget_list(struct scroll_bar *vscroll,
388 struct widget *begin_active_widget_list,
389 struct widget *begin_widget_list,
390 struct widget *end_widget_list);
391
392static struct widget *down_scroll_widget_list(struct scroll_bar *vscroll,
393 struct widget *begin_active_widget_list,
394 struct widget *begin_widget_list,
395 struct widget *end_widget_list);
396
397static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
398 struct widget *begin_active_widget_list,
399 struct widget *begin_widget_list,
400 struct widget *end_widget_list);
401
402/**********************************************************************/
405static int std_up_advanced_dlg_callback(struct widget *pwidget)
406{
408 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
409 struct widget *begin = up_scroll_widget_list(
410 dlg->scroll,
414
415 if (begin) {
416 dlg->active_widget_list = begin;
417 }
418
420 selected_widget = pwidget;
421 set_wstate(pwidget, FC_WS_SELECTED);
422 widget_redraw(pwidget);
423 widget_flush(pwidget);
424 }
425
426 return -1;
427}
428
429/**********************************************************************/
432static int std_down_advanced_dlg_callback(struct widget *pwidget)
433{
435 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
436 struct widget *begin = down_scroll_widget_list(
437 dlg->scroll,
441
442 if (begin) {
443 dlg->active_widget_list = begin;
444 }
445
447 selected_widget = pwidget;
448 set_wstate(pwidget, FC_WS_SELECTED);
449 widget_redraw(pwidget);
450 widget_flush(pwidget);
451 }
452
453 return -1;
454}
455
456/**********************************************************************/
459static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
460{
462 struct advanced_dialog *dlg = pscroll_bar->private_data.adv_dlg;
463 struct widget *begin = vertic_scroll_widget_list(
464 dlg->scroll,
468
469 if (begin) {
470 dlg->active_widget_list = begin;
471 }
472
474 set_wstate(pscroll_bar, FC_WS_SELECTED);
475 selected_widget = pscroll_bar;
476 redraw_vert(pscroll_bar);
477 widget_flush(pscroll_bar);
478 }
479
480 return -1;
481}
482
483/**********************************************************************/
487 Uint8 step, Uint8 active,
489{
490 Uint16 count = 0;
491 struct widget *buf = NULL, *pwindow = NULL;
492
493 fc_assert_ret_val(dlg != NULL, 0);
494
495 pwindow = dlg->end_widget_list;
496
497 if (!dlg->scroll) {
498 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
499
501 while (buf && (buf != dlg->begin_active_widget_list->prev)) {
502 buf = buf->prev;
503 count++;
504 }
505
506 dlg->scroll->count = count;
507 }
508
509 dlg->scroll->active = active;
510 dlg->scroll->step = step;
511
512 if (create_buttons) {
513 /* create up button */
514 buf = create_themeicon_button(current_theme->up_icon, pwindow->dst,
516
517 buf->id = ID_BUTTON;
518 buf->private_data.adv_dlg = dlg;
521
522 dlg->scroll->up_left_button = buf;
524 dlg->begin_widget_list = buf;
525
526 count = buf->size.w;
527
528 /* create down button */
529 buf = create_themeicon_button(current_theme->down_icon, pwindow->dst,
531
532 buf->id = ID_BUTTON;
533 buf->private_data.adv_dlg = dlg;
536
539 dlg->begin_widget_list = buf;
540 }
541
542 if (create_scrollbar) {
543 /* create vscrollbar */
544 buf = create_vertical(current_theme->vertic, pwindow->dst,
546
547 buf->id = ID_SCROLLBAR;
548 buf->private_data.adv_dlg = dlg;
551
552 dlg->scroll->pscroll_bar = buf;
554 dlg->begin_widget_list = buf;
555
556 if (!count) {
557 count = buf->size.w;
558 }
559 }
560
561 return count;
562}
563
564/**********************************************************************/
568 Sint16 start_x, Sint16 start_y,
570{
571 bool buttons_exist;
572
573 fc_assert_ret(scroll != NULL);
574
575 buttons_exist = (scroll->down_right_button && scroll->up_left_button);
576
577 if (buttons_exist) {
578 /* up */
579 scroll->up_left_button->size.y = start_y;
580 if (swap_start_x) {
581 scroll->up_left_button->size.x = start_x -
582 scroll->up_left_button->size.w;
583 } else {
584 scroll->up_left_button->size.x = start_x;
585 }
586 scroll->min = start_y + scroll->up_left_button->size.h;
587 /* -------------------------- */
588 /* down */
589 scroll->down_right_button->size.y = start_y + height -
590 scroll->down_right_button->size.h;
591 if (swap_start_x) {
592 scroll->down_right_button->size.x = start_x -
593 scroll->down_right_button->size.w;
594 } else {
595 scroll->down_right_button->size.x = start_x;
596 }
597 scroll->max = scroll->down_right_button->size.y;
598 }
599 /* --------------- */
600 /* scrollbar */
601 if (scroll->pscroll_bar) {
602 if (swap_start_x) {
603 scroll->pscroll_bar->size.x = start_x - scroll->pscroll_bar->size.w + 2;
604 } else {
605 scroll->pscroll_bar->size.x = start_x;
606 }
607
608 if (buttons_exist) {
609 scroll->pscroll_bar->size.y = start_y +
610 scroll->up_left_button->size.h;
611 if (scroll->count > scroll->active * scroll->step) {
612 scroll->pscroll_bar->size.h = scrollbar_size(scroll);
613 } else {
614 scroll->pscroll_bar->size.h = scroll->max - scroll->min;
615 }
616 } else {
617 scroll->pscroll_bar->size.y = start_y;
618 scroll->pscroll_bar->size.h = height;
619 scroll->min = start_y;
620 scroll->max = start_y + height;
621 }
622 }
623}
624
625/* =================================================== */
626/* ============ Vertical Scroll Group List =========== */
627/* =================================================== */
628
629/**********************************************************************/
633static struct widget *vertical_scroll_widget_list(struct widget *active_widget_list,
634 struct widget *begin_widget_list,
635 struct widget *end_widget_list,
636 int active, int step, int dir)
637{
638 struct widget *begin = active_widget_list;
639 struct widget *buf = active_widget_list;
640 struct widget *tmp = NULL;
641 int count = active; /* row */
642 int count_step = step; /* col */
643
644 if (dir < 0) {
645 /* up */
646 bool real = TRUE;
647
648 if (buf != end_widget_list) {
649 /*
650 move pointers to positions and unhide scrolled widgets
651 B = buf - new top
652 T = tmp - current top == active_widget_list
653 [B] [ ] [ ]
654 -----------
655 [T] [ ] [ ]
656 [ ] [ ] [ ]
657 -----------
658 [ ] [ ] [ ]
659 */
660 tmp = buf; /* now buf == active_widget_list == current Top */
661 while (count_step > 0) {
662 buf = buf->next;
664 count_step--;
665 }
667
668 /* setup new ActiveWidget pointer */
669 begin = buf;
670
671 /*
672 scroll pointers up
673 B = buf
674 T = tmp
675 [B0] [B1] [B2]
676 -----------
677 [T0] [T1] [T2] => B position = T position
678 [T3] [T4] [T5]
679 -----------
680 [ ] [ ] [ ]
681
682 start from B0 and go down list
683 B0 = T0, B1 = T1, B2 = T2
684 T0 = T3, T1 = T4, T2 = T5
685 etc...
686 */
687
688 /* buf == begin == new top widget */
689
690 while (count > 0) {
691 if (real) {
692 buf->size.x = tmp->size.x;
693 buf->size.y = tmp->size.y;
694 buf->gfx = tmp->gfx;
695
696 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
701 }
702 }
703
704 tmp->gfx = NULL;
705
706 if (count == 1) {
708 }
709 if (tmp == begin_widget_list) {
710 real = FALSE;
711 }
712 tmp = tmp->prev;
713 } else {
714 /*
715 unsymmetric list support.
716 This is big problem because we can't take position from unexisting
717 list member. We must put here some hypothetical positions
718
719 [B0] [B1] [B2]
720 --------------
721 [T0] [T1]
722
723 */
724 if (active > 1) {
725 /* this works well if active > 1 but is buggy when active == 1 */
726 buf->size.y += buf->size.h;
727 } else {
728 /* this works well if active == 1 but may be broken if "next"
729 element has other "y" position */
730 buf->size.y = buf->next->size.y;
731 }
732 buf->gfx = NULL;
733 }
734
735 buf = buf->prev;
736 count_step--;
737 if (!count_step) {
739 count--;
740 }
741 }
742 }
743 } else {
744 /* down */
745 count = active * step; /* row * col */
746
747 /*
748 find end
749 B = buf
750 A - start (buf == active_widget_list)
751 [ ] [ ] [ ]
752 -----------
753 [A] [ ] [ ]
754 [ ] [ ] [ ]
755 -----------
756 [B] [ ] [ ]
757 */
758 while (count && buf != begin_widget_list->prev) {
759 buf = buf->prev;
760 count--;
761 }
762
763 if (!count && buf != begin_widget_list->prev) {
764 /*
765 move pointers to positions and unhide scrolled widgets
766 B = buf
767 T = tmp
768 A - start (active_widget_list)
769 [ ] [ ] [ ]
770 -----------
771 [A] [ ] [ ]
772 [ ] [ ] [T]
773 -----------
774 [ ] [ ] [B]
775 */
776 tmp = buf->next;
777 count_step = step - 1;
778 while (count_step && buf != begin_widget_list) {
780 buf = buf->prev;
781 count_step--;
782 }
784
785 /*
786 Unsymmetric list support.
787 correct tmp and undraw empty fields
788 B = buf
789 T = tmp
790 A - start (active_widget_list)
791 [ ] [ ] [ ]
792 -----------
793 [A] [ ] [ ]
794 [ ] [T] [U] <- undraw U
795 -----------
796 [ ] [B]
797 */
798 count = count_step;
799 while (count) {
800 /* hack - clear area under unexisting list members */
803 FREESURFACE(tmp->gfx);
804 if (active == 1) {
806 }
807 tmp = tmp->next;
808 count--;
809 }
810
811 /* reset counters */
812 count = active;
813 if (count_step) {
815 } else {
817 }
818
819 /*
820 scroll pointers down
821 B = buf
822 T = tmp
823 [ ] [ ] [ ]
824 -----------
825 [ ] [ ] [ ]
826 [T2] [T1] [T0] => B position = T position
827 -----------
828 [B2] [B1] [B0]
829 */
830 while (count) {
831 buf->size.x = tmp->size.x;
832 buf->size.y = tmp->size.y;
833 buf->gfx = tmp->gfx;
834
835 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
840 }
841 }
842
843 tmp->gfx = NULL;
844
845 if (count == 1) {
847 }
848
849 tmp = tmp->next;
850 buf = buf->next;
851 count_step--;
852 if (!count_step) {
854 count--;
855 }
856 }
857 /* setup new ActiveWidget pointer */
858 begin = buf->prev;
859 }
860 }
861
862 return begin;
863}
864
865/**********************************************************************/
869{
870 struct UP_DOWN *down = (struct UP_DOWN *)data;
871
872 if (down->end != down->begin_widget_list) {
873 if (down->vscroll->pscroll_bar
874 && down->vscroll->pscroll_bar->size.y <=
875 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
876
877 /* draw bcgd */
880
881 if (down->vscroll->pscroll_bar->size.y + down->step >
882 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
883 down->vscroll->pscroll_bar->size.y =
884 down->vscroll->max - down->vscroll->pscroll_bar->size.h;
885 } else {
886 down->vscroll->pscroll_bar->size.y += down->step;
887 }
888 }
889
892 down->vscroll->active, down->vscroll->step, 1);
893
894 down->end = down->end->prev;
895
897
898 if (down->vscroll->pscroll_bar) {
899 /* Redraw scrollbar */
902 }
904
906 }
907
908 flush_dirty();
909 }
910}
911
912/**********************************************************************/
915static void inside_scroll_up_loop(void *data)
916{
917 struct UP_DOWN *up = (struct UP_DOWN *)data;
918
919 if (up && up->begin != up->end_widget_list) {
920
921 if (up->vscroll->pscroll_bar
922 && (up->vscroll->pscroll_bar->size.y >= up->vscroll->min)) {
923
924 /* draw bcgd */
927
928 if (((up->vscroll->pscroll_bar->size.y - up->step) < up->vscroll->min)) {
929 up->vscroll->pscroll_bar->size.y = up->vscroll->min;
930 } else {
931 up->vscroll->pscroll_bar->size.y -= up->step;
932 }
933 }
934
937 up->vscroll->active, up->vscroll->step, -1);
938
940
941 if (up->vscroll->pscroll_bar) {
942 /* Redraw scrollbar */
945 }
948 }
949
950 flush_dirty();
951 }
952}
953
954/**********************************************************************/
958 void *data)
959{
960 struct UP_DOWN *motion = (struct UP_DOWN *)data;
961 int yrel;
962 int y;
963 int normalized_y;
964 int net_slider_area;
965 int net_count;
966 float scroll_step;
967
968 yrel = motion_event->y - motion->prev_y;
969 motion->prev_x = motion_event->x;
970 motion->prev_y = motion_event->y;
971
972 y = motion_event->y - motion->vscroll->pscroll_bar->dst->dest_rect.y;
973
974 normalized_y = (y - motion->offset);
975
976 net_slider_area = (motion->vscroll->max - motion->vscroll->min - motion->vscroll->pscroll_bar->size.h);
977 net_count = round((float)motion->vscroll->count / motion->vscroll->step) - motion->vscroll->active + 1;
979
980 if ((yrel != 0)
981 && ((normalized_y >= motion->vscroll->min)
983 && (motion->vscroll->pscroll_bar->size.y > motion->vscroll->min)))
984 && ((normalized_y <= motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)
985 || ((normalized_y > motion->vscroll->max)
986 && (motion->vscroll->pscroll_bar->size.y < (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)))) ) {
987 int count;
988
989 /* Draw bcgd */
990 widget_undraw(motion->vscroll->pscroll_bar);
991 widget_mark_dirty(motion->vscroll->pscroll_bar);
992
993 if ((motion->vscroll->pscroll_bar->size.y + yrel) >
994 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)) {
995
996 motion->vscroll->pscroll_bar->size.y =
997 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h);
998
999 } else if ((motion->vscroll->pscroll_bar->size.y + yrel) < motion->vscroll->min) {
1000 motion->vscroll->pscroll_bar->size.y = motion->vscroll->min;
1001 } else {
1002 motion->vscroll->pscroll_bar->size.y += yrel;
1003 }
1004
1005 count = round((motion->vscroll->pscroll_bar->size.y - motion->old_y) / scroll_step);
1006
1007 if (count != 0) {
1008 int i = count;
1009
1010 while (i != 0) {
1012 motion->begin_widget_list,
1013 motion->end_widget_list,
1014 motion->vscroll->active,
1015 motion->vscroll->step, i);
1016 if (i > 0) {
1017 i--;
1018 } else {
1019 i++;
1020 }
1021 } /* while (i != 0) */
1022
1023 motion->old_y = motion->vscroll->min +
1024 ((round((motion->old_y - motion->vscroll->min) / scroll_step) + count) * scroll_step);
1025
1026 redraw_group(motion->begin_widget_list, motion->end_widget_list, TRUE);
1027 }
1028
1029 /* Redraw slider */
1030 if (get_wflags(motion->vscroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
1031 refresh_widget_background(motion->vscroll->pscroll_bar);
1032 }
1033 redraw_vert(motion->vscroll->pscroll_bar);
1034 widget_mark_dirty(motion->vscroll->pscroll_bar);
1035
1036 flush_dirty();
1037 }
1038
1039 return ID_ERROR;
1040}
1041
1042/**********************************************************************/
1046 void *data)
1047{
1048 return (Uint16)ID_SCROLLBAR;
1049}
1050
1051/**********************************************************************/
1054static struct widget *down_scroll_widget_list(struct scroll_bar *vscroll,
1055 struct widget *begin_active_widget_list,
1056 struct widget *begin_widget_list,
1057 struct widget *end_widget_list)
1058{
1059 struct UP_DOWN down;
1060 struct widget *begin = begin_active_widget_list;
1061 int step = vscroll->active * vscroll->step - 1;
1062
1063 while (step--) {
1064 begin = begin->prev;
1065 }
1066
1067 down.step = get_step(vscroll);
1068 down.begin = begin_active_widget_list;
1069 down.end = begin;
1070 down.begin_widget_list = begin_widget_list;
1071 down.end_widget_list = end_widget_list;
1072 down.vscroll = vscroll;
1073
1076
1077 return down.begin;
1078}
1079
1080/**********************************************************************/
1083static struct widget *up_scroll_widget_list(struct scroll_bar *vscroll,
1084 struct widget *begin_active_widget_list,
1085 struct widget *begin_widget_list,
1086 struct widget *end_widget_list)
1087{
1088 struct UP_DOWN up;
1089
1090 up.step = get_step(vscroll);
1091 up.begin = begin_active_widget_list;
1094 up.vscroll = vscroll;
1095
1098
1099 return up.begin;
1100}
1101
1102/**********************************************************************/
1105static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
1106 struct widget *begin_active_widget_list,
1107 struct widget *begin_widget_list,
1108 struct widget *end_widget_list)
1109{
1110 struct UP_DOWN motion;
1111
1113 motion.begin = begin_active_widget_list;
1114 motion.begin_widget_list = begin_widget_list;
1115 motion.end_widget_list = end_widget_list;
1116 motion.vscroll = vscroll;
1117 motion.old_y = vscroll->pscroll_bar->size.y;
1118 SDL_GetMouseState(&motion.prev_x, &motion.prev_y);
1119 motion.offset = motion.prev_y - vscroll->pscroll_bar->dst->dest_rect.y - vscroll->pscroll_bar->size.y;
1120
1121 MOVE_STEP_X = 0;
1122 MOVE_STEP_Y = 3;
1123 /* Filter mouse motion events */
1127 /* Turn off Filter mouse motion events */
1131
1132 return motion.begin;
1133}
1134
1135/* ==================================================================== */
1136
1137/**********************************************************************/
1147 struct widget *new_widget,
1148 struct widget *add_dock,
1149 bool dir,
1150 Sint16 start_x, Sint16 start_y)
1151{
1152 struct widget *buf = NULL;
1153 struct widget *end = NULL, *old_end = NULL;
1154 bool last = FALSE, seen = TRUE;
1155
1156 fc_assert_ret_val(dlg != NULL, FALSE);
1158
1159 if (!add_dock) {
1160 add_dock = dlg->begin_widget_list; /* Last item */
1161 }
1162
1163 dlg->scroll->count++;
1164
1165 if (dlg->scroll->count > (dlg->scroll->active * dlg->scroll->step)) {
1166 /* -> Scrollbar needed */
1167
1168 if (dlg->active_widget_list) {
1169 /* -> Scrollbar is already visible */
1170 int i = 0;
1171
1172 /* Find last active widget */
1173 old_end = add_dock;
1174 while (old_end != dlg->active_widget_list) {
1175 old_end = old_end->next;
1176 i++;
1177 if (old_end == dlg->end_active_widget_list) {
1178 /* Implies (old_end == dlg->active_widget_list)? */
1179 seen = FALSE;
1180 break;
1181 }
1182 }
1183
1184 if (seen) {
1185 int count = (dlg->scroll->active * dlg->scroll->step) - 1;
1186
1187 if (i > count) {
1188 seen = FALSE;
1189 } else {
1190 while (count > 0) {
1191 old_end = old_end->prev;
1192 count--;
1193 }
1194 if (old_end == add_dock) {
1195 last = TRUE;
1196 }
1197 }
1198 }
1199
1200 } else {
1201 last = TRUE;
1203 show_scrollbar(dlg->scroll);
1204 }
1205 }
1206
1207 /* Add pointer to list */
1208 if (dir) {
1209 /* Upper add */
1211
1212 if (add_dock == dlg->end_widget_list) {
1214 }
1215 if (add_dock == dlg->end_active_widget_list) {
1217 }
1218 if (add_dock == dlg->active_widget_list) {
1220 }
1221 } else {
1222 /* Down add */
1224
1225 if (add_dock == dlg->begin_widget_list) {
1227 }
1228
1229 if (add_dock == dlg->begin_active_widget_list) {
1231 }
1232 }
1233
1234 /* Setup draw positions */
1235 if (seen) {
1236 if (!dlg->begin_active_widget_list) {
1237 /* First element ( active list empty ) */
1238 fc_assert_msg(!dir, "Forbidden List Operation");
1239
1240 new_widget->size.x = start_x;
1241 new_widget->size.y = start_y;
1244 if (!dlg->begin_widget_list) {
1247 }
1248 } else {
1249 /* There are some elements on local active list */
1250 if (last) {
1251 /* We add to last seen position */
1252 if (dir) {
1253 /* Only swap add_dock with new_widget on last seen positions */
1254 new_widget->size.x = add_dock->size.x;
1255 new_widget->size.y = add_dock->size.y;
1256 new_widget->gfx = add_dock->gfx;
1257 add_dock->gfx = NULL;
1259 } else {
1260 /* Reposition all widgets */
1261 buf = new_widget;
1262 do {
1263 buf->size.x = buf->next->size.x;
1264 buf->size.y = buf->next->size.y;
1265 buf->gfx = buf->next->gfx;
1266 buf->next->gfx = NULL;
1267 buf = buf->next;
1268 } while (buf != dlg->active_widget_list);
1269 buf->gfx = NULL;
1272 }
1273 } else { /* !last */
1274 buf = new_widget;
1275 /* Find last seen widget */
1276 if (dlg->active_widget_list) {
1277 int count = dlg->scroll->active * dlg->scroll->step - 1;
1278
1279 end = dlg->active_widget_list;
1280 while (count && end != dlg->begin_active_widget_list) {
1281 end = end->prev;
1282 count--;
1283 }
1284 }
1285 while (buf) {
1286 if (buf == dlg->begin_active_widget_list) {
1287 struct widget *tmp = buf;
1288 int count = dlg->scroll->step;
1289
1290 while (count) {
1291 tmp = tmp->next;
1292 count--;
1293 }
1294 buf->size.x = tmp->size.x;
1295 buf->size.y = tmp->size.y + tmp->size.h;
1296 /* Break when last active widget or last seen widget */
1297 break;
1298 } else {
1299 buf->size.x = buf->prev->size.x;
1300 buf->size.y = buf->prev->size.y;
1301 buf->gfx = buf->prev->gfx;
1302 buf->prev->gfx = NULL;
1303 if (buf == end) {
1304 break;
1305 }
1306 }
1307 buf = buf->prev;
1308 }
1309 if (old_end && buf->prev == old_end) {
1311 }
1312 } /* !last */
1313 } /* dlg->begin_active_widget_list */
1314 } else {
1315 /* Not seen */
1317 }
1318
1319 if (dlg->active_widget_list && dlg->scroll->pscroll_bar) {
1322
1323 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1324 if (last) {
1325 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1326 }
1329 }
1330 if (!seen) {
1332 }
1333 }
1334
1335 return last;
1336}
1337
1338/**********************************************************************/
1345 struct widget *pwidget)
1346{
1347 struct widget *buf = pwidget;
1348
1349 fc_assert_ret_val(dlg != NULL, FALSE);
1350
1351 /* If begin == end -> size = 1 */
1353
1354 if (dlg->scroll) {
1355 dlg->scroll->count = 0;
1356 }
1357
1360 }
1361
1362 if (dlg->end_active_widget_list == dlg->end_widget_list) {
1364 }
1365
1367 dlg->active_widget_list = NULL;
1369
1370 widget_undraw(pwidget);
1371 widget_mark_dirty(pwidget);
1372 del_widget_from_gui_list(pwidget);
1373
1374 return FALSE;
1375 }
1376
1377 if (dlg->scroll && dlg->active_widget_list) {
1378 /* Scrollbar exist and active, start mod. from last seen label */
1379 struct widget *last;
1380 bool widget_found = FALSE;
1381 int count;
1382
1383 /* This is always true because no-scrolbar case (active * step < count)
1384 will be supported in other part of code (see "else" part) */
1385 count = dlg->scroll->active * dlg->scroll->step;
1386
1387 /* Find last */
1388 buf = dlg->active_widget_list;
1389 while (count > 0) {
1390 buf = buf->prev;
1391 count--;
1392 }
1393 if (!buf) {
1394 last = dlg->begin_active_widget_list;
1395 } else {
1396 last = buf->next;
1397 }
1398
1399 if (last == dlg->begin_active_widget_list) {
1400 if (dlg->scroll->step == 1) {
1403
1404 /* Look for the widget in the non-visible part */
1406 while (buf != dlg->active_widget_list) {
1407 if (buf == pwidget) {
1409 buf = dlg->active_widget_list;
1410 break;
1411 }
1412 buf = buf->prev;
1413 }
1414
1415 /* If we haven't found it yet, look in the visible part and update the
1416 * positions of the other widgets */
1417 if (!widget_found) {
1418 while (buf != pwidget) {
1419 buf->gfx = buf->prev->gfx;
1420 buf->prev->gfx = NULL;
1421 buf->size.x = buf->prev->size.x;
1422 buf->size.y = buf->prev->size.y;
1423 buf = buf->prev;
1424 }
1425 }
1426 } else {
1427 buf = last;
1428 /* Undraw last widget */
1431 FREESURFACE(buf->gfx);
1432 goto std;
1433 }
1434 } else {
1436
1437std: while (buf != pwidget) {
1438 buf->gfx = buf->next->gfx;
1439 buf->next->gfx = NULL;
1440 buf->size.x = buf->next->size.x;
1441 buf->size.y = buf->next->size.y;
1442 buf = buf->next;
1443 }
1444 }
1445
1446 if ((dlg->scroll->count - 1) <= (dlg->scroll->active * dlg->scroll->step)) {
1447 /* Scrollbar not needed anymore */
1448 hide_scrollbar(dlg->scroll);
1449 dlg->active_widget_list = NULL;
1450 }
1451 dlg->scroll->count--;
1452
1453 if (dlg->active_widget_list) {
1454 if (dlg->scroll->pscroll_bar) {
1456 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1458 }
1459 }
1460
1461 } else {
1462 /* No scrollbar */
1464
1465 /* Undraw last widget */
1468 FREESURFACE(buf->gfx);
1469
1470 while (buf != pwidget) {
1471 buf->gfx = buf->next->gfx;
1472 buf->next->gfx = NULL;
1473 buf->size.x = buf->next->size.x;
1474 buf->size.y = buf->next->size.y;
1475 buf = buf->next;
1476 }
1477
1478 if (dlg->scroll) {
1479 dlg->scroll->count--;
1480 }
1481 }
1482
1483 if (pwidget == dlg->begin_widget_list) {
1484 dlg->begin_widget_list = pwidget->next;
1485 }
1486
1487 if (pwidget == dlg->begin_active_widget_list) {
1488 dlg->begin_active_widget_list = pwidget->next;
1489 }
1490
1491 if (pwidget == dlg->end_active_widget_list) {
1492 if (pwidget == dlg->end_widget_list) {
1493 dlg->end_widget_list = pwidget->prev;
1494 }
1495
1496 if (pwidget == dlg->active_widget_list) {
1497 dlg->active_widget_list = pwidget->prev;
1498 }
1499
1500 dlg->end_active_widget_list = pwidget->prev;
1501
1502 }
1503
1504 if (dlg->active_widget_list && (dlg->active_widget_list == pwidget)) {
1505 dlg->active_widget_list = pwidget->prev;
1506 }
1507
1508 del_widget_from_gui_list(pwidget);
1509
1510 if (dlg->scroll && dlg->scroll->pscroll_bar && dlg->active_widget_list) {
1512 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1514 }
1515
1516 return TRUE;
1517}
1518
1519/**********************************************************************/
1523{
1524 fc_assert_ret(scroll != NULL);
1525
1526 if (scroll->up_left_button) {
1528 }
1529 if (scroll->down_right_button) {
1531 }
1532 if (scroll->pscroll_bar) {
1534 }
1535}
1536
1537/**************************************************************************
1538 Horizontal Scrollbar
1539**************************************************************************/
1540
1541
1542/**********************************************************************/
1546 Sint16 start_x, Sint16 start_y,
1547 Uint16 width, Uint16 active,
1549 bool swap_start_y)
1550{
1551 Uint16 count = 0;
1552 struct widget *buf = NULL, *pwindow = NULL;
1553
1554 fc_assert_ret_val(dlg != NULL, 0);
1555
1556 pwindow = dlg->end_widget_list;
1557
1558 if (!dlg->scroll) {
1559 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
1560
1561 dlg->scroll->active = active;
1562
1564 while (buf && buf != dlg->begin_active_widget_list->prev) {
1565 buf = buf->prev;
1566 count++;
1567 }
1568
1569 dlg->scroll->count = count;
1570 }
1571
1572 if (create_buttons) {
1573 /* create up button */
1574 buf = create_themeicon_button(current_theme->left_icon, pwindow->dst, NULL, 0);
1575
1576 buf->id = ID_BUTTON;
1577 buf->data.ptr = (void *)dlg;
1579
1580 buf->size.x = start_x;
1581 if (swap_start_y) {
1582 buf->size.y = start_y - buf->size.h;
1583 } else {
1584 buf->size.y = start_y;
1585 }
1586
1587 dlg->scroll->min = start_x + buf->size.w;
1588 dlg->scroll->up_left_button = buf;
1590 dlg->begin_widget_list = buf;
1591
1592 count = buf->size.h;
1593
1594 /* create down button */
1595 buf = create_themeicon_button(current_theme->right_icon, pwindow->dst, NULL, 0);
1596
1597 buf->id = ID_BUTTON;
1598 buf->data.ptr = (void *)dlg;
1600
1601 buf->size.x = start_x + width - buf->size.w;
1602 if (swap_start_y) {
1603 buf->size.y = start_y - buf->size.h;
1604 } else {
1605 buf->size.y = start_y;
1606 }
1607
1608 dlg->scroll->max = buf->size.x;
1611 dlg->begin_widget_list = buf;
1612 }
1613
1614 if (create_scrollbar) {
1615 /* create vscrollbar */
1616 buf = create_horizontal(current_theme->horiz, pwindow->dst,
1618
1619 buf->id = ID_SCROLLBAR;
1620 buf->data.ptr = (void *)dlg;
1622
1623 if (swap_start_y) {
1624 buf->size.y = start_y - buf->size.h;
1625 } else {
1626 buf->size.y = start_y;
1627 }
1628
1629 if (create_buttons) {
1630 buf->size.x = start_x + dlg->scroll->up_left_button->size.w;
1631 if (dlg->scroll->count > dlg->scroll->active) {
1632 buf->size.w = scrollbar_size(dlg->scroll);
1633 } else {
1634 buf->size.w = dlg->scroll->max - dlg->scroll->min;
1635 }
1636 } else {
1637 buf->size.x = start_x;
1638 dlg->scroll->min = start_x;
1639 dlg->scroll->max = start_x + width;
1640 }
1641
1642 dlg->scroll->pscroll_bar = buf;
1644 dlg->begin_widget_list = buf;
1645
1646 if (!count) {
1647 count = buf->size.h;
1648 }
1649 }
1650
1651 return count;
1652}
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:75
QString current_theme
Definition fc_client.cpp:65
void flush_dirty(void)
Definition mapview.c:468
SDL_Surface * crop_rect_from_surface(SDL_Surface *psource, SDL_Rect *prect)
Definition graphics.c:236
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:199
struct sdl2_data main_data
Definition graphics.c:57
int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest, Sint16 dest_x, Sint16 dest_y)
Definition graphics.c:417
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:351
#define FREESURFACE(ptr)
Definition graphics.h:322
@ ID_ERROR
Definition gui_id.h:26
@ ID_BUTTON
Definition gui_id.h:29
@ ID_SCROLLBAR
Definition gui_id.h:32
int FilterMouseMotionEvents(void *data, SDL_Event *event)
Definition gui_main.c:581
Uint16 gui_event_loop(void *data, void(*loop_action)(void *data), Uint16(*key_down_handler)(SDL_Keysym key, void *data), Uint16(*key_up_handler)(SDL_Keysym key, void *data), Uint16(*textinput_handler)(const char *text, void *data), Uint16(*finger_down_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*finger_up_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*finger_motion_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*mouse_button_down_handler)(SDL_MouseButtonEvent *button_event, void *data), Uint16(*mouse_button_up_handler)(SDL_MouseButtonEvent *button_event, void *data), Uint16(*mouse_motion_handler)(SDL_MouseMotionEvent *motion_event, void *data))
Definition gui_main.c:602
int MOVE_STEP_Y
Definition gui_main.c:105
int MOVE_STEP_X
Definition gui_main.c:104
struct widget * selected_widget
Definition widget.c:48
#define adj_size(size)
Definition gui_main.h:141
#define DEFAULT_MOVE_STEP
Definition gui_main.h:113
#define PRESSED_EVENT(event)
Definition gui_main.h:71
void refresh_widget_background(struct widget *pwidget)
Definition widget.c:1151
void unselect_widget_action(void)
Definition widget.c:418
void widget_add_as_prev(struct widget *new_widget, struct widget *add_dock)
Definition widget.c:602
Uint16 redraw_group(const struct widget *begin_group_widget_list, const struct widget *end_group_widget_list, int add_to_update)
Definition widget.c:720
widget_state
Definition widget.h:95
@ FC_WS_DISABLED
Definition widget.h:99
@ FC_WS_NORMAL
Definition widget.h:96
@ FC_WS_SELECTED
Definition widget.h:97
void clear_wflag(struct widget *pwidget, enum widget_flag flag)
Definition widget_core.c:62
static void widget_mark_dirty(struct widget *pwidget)
Definition widget.h:286
static void widget_flush(struct widget *pwidget)
Definition widget.h:291
enum widget_flag get_wflags(const struct widget *pwidget)
Definition widget_core.c:86
void set_wstate(struct widget *pwidget, enum widget_state state)
Definition widget_core.c:36
enum widget_state get_wstate(const struct widget *pwidget)
Definition widget_core.c:70
static void widget_undraw(struct widget *pwidget)
Definition widget.h:296
@ WF_FREE_GFX
Definition widget.h:70
@ WF_FREE_STRING
Definition widget.h:76
@ WF_RESTORE_BACKGROUND
Definition widget.h:85
@ WF_HIDDEN
Definition widget.h:68
static int widget_redraw(struct widget *pwidget)
Definition widget.h:276
#define del_widget_from_gui_list(__gui)
Definition widget.h:372
void set_wtype(struct widget *pwidget, enum widget_type type)
Definition widget_core.c:45
void set_wflag(struct widget *pwidget, enum widget_flag flag)
Definition widget_core.c:54
@ WT_VSCROLLBAR
Definition widget.h:50
@ WT_HSCROLLBAR
Definition widget.h:51
struct widget * create_themeicon_button(SDL_Surface *icon_theme, struct gui_layer *pdest, utf8_str *pstr, Uint32 flags)
struct widget * widget_new(void)
static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
static int std_down_advanced_dlg_callback(struct widget *pwidget)
static int redraw_horiz(struct widget *horiz)
static struct widget * vertical_scroll_widget_list(struct widget *active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list, int active, int step, int dir)
static Uint16 scroll_mouse_button_up(SDL_MouseButtonEvent *button_event, void *data)
int draw_vert(struct widget *vert, Sint16 x, Sint16 y)
static int redraw_vert(struct widget *vert)
bool del_widget_from_vertical_scroll_widget_list(struct advanced_dialog *dlg, struct widget *pwidget)
Uint32 create_horizontal_scrollbar(struct advanced_dialog *dlg, Sint16 start_x, Sint16 start_y, Uint16 width, Uint16 active, bool create_scrollbar, bool create_buttons, bool swap_start_y)
#define widget_add_next(new_widget, add_dock)
static struct widget * down_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
struct widget * create_horizontal(SDL_Surface *horiz_theme, struct gui_layer *pdest, Uint16 width, Uint32 flags)
static int(* baseclass_redraw)(struct widget *pwidget)
static struct widget * up_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
static Uint16 scroll_mouse_motion_handler(SDL_MouseMotionEvent *motion_event, void *data)
static struct widget * vertic_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
void setup_vertical_scrollbar_default_callbacks(struct scroll_bar *scroll)
struct widget * create_vertical(SDL_Surface *vert_theme, struct gui_layer *pdest, Uint16 height, Uint32 flags)
static void inside_scroll_up_loop(void *data)
static int get_position(struct advanced_dialog *dlg)
void setup_vertical_scrollbar_area(struct scroll_bar *scroll, Sint16 start_x, Sint16 start_y, Uint16 height, bool swap_start_x)
bool add_widget_to_vertical_scroll_widget_list(struct advanced_dialog *dlg, struct widget *new_widget, struct widget *add_dock, bool dir, Sint16 start_x, Sint16 start_y)
static void inside_scroll_down_loop(void *data)
static int get_step(struct scroll_bar *scroll)
Uint32 create_vertical_scrollbar(struct advanced_dialog *dlg, Uint8 step, Uint8 active, bool create_scrollbar, bool create_buttons)
static int std_up_advanced_dlg_callback(struct widget *pwidget)
static SDL_Surface * create_vertical_surface(SDL_Surface *vert_theme, enum widget_state state, Uint16 height)
static SDL_Surface * create_horizontal_surface(SDL_Surface *horiz_theme, enum widget_state state, Uint16 width)
#define hide_scrollbar(scrollbar)
#define show_scrollbar(scrollbar)
#define scrollbar_size(scroll)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_calloc(n, esz)
Definition mem.h:38
int step
Definition specpq.h:92
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
struct widget * end_widget_list
struct widget * begin_widget_list
struct scroll_bar * vscroll
struct widget * begin
struct widget * end
struct widget * begin_active_widget_list
Definition widget.h:184
struct widget * end_widget_list
Definition widget.h:182
struct widget * end_active_widget_list
Definition widget.h:185
struct widget * active_widget_list
Definition widget.h:186
struct scroll_bar * scroll
Definition widget.h:187
struct widget * begin_widget_list
Definition widget.h:181
SDL_Surface * surface
Definition graphics.h:229
SDL_Rect dest_rect
Definition graphics.h:228
struct widget * up_left_button
struct widget * down_right_button
struct widget * pscroll_bar
SDL_Event event
Definition graphics.h:217
union widget::@194 data
SDL_Surface * theme
Definition widget.h:118
struct widget * prev
Definition widget.h:114
struct gui_layer * dst
Definition widget.h:116
struct advanced_dialog * adv_dlg
Definition widget.h:139
int(* action)(struct widget *)
Definition widget.h:157
union widget::@195 private_data
SDL_Surface * gfx
Definition widget.h:120
struct widget * next
Definition widget.h:113
SDL_Rect size
Definition widget.h:145
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47