Freeciv-3.1
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/**********************************************************************/
213 Uint8 state, Uint16 width)
214{
216 SDL_Rect src, des;
217 Uint16 i;
218 Uint16 start_x;
222
223 tile_len_end = horiz_theme->w / 16;
224
225 start_x = 0 + state * (horiz_theme->w / 4);
226
228
230
231 /* Correction */
234 }
235
236 if (!tile_count_midd) {
238 } else {
240 }
241
242 src.y = 0;
243 src.x = start_x;
244 src.h = horiz_theme->h;
245 src.w = tile_len_end;
246 alphablit(horiz_theme, &src, horsurf, NULL, 255);
247
248 src.x = start_x + tile_len_end;
249 src.w = tile_len_midd;
250
251 des.y = 0;
252
253 for (i = 0; i < tile_count_midd; i++) {
255 alphablit(horiz_theme, &src, horsurf, &des, 255);
256 }
257
258 src.x = start_x + tile_len_end + tile_len_midd;
259 src.w = tile_len_end;
260 des.x = horsurf->w - tile_len_end;
261 alphablit(horiz_theme, &src, horsurf, &des, 255);
262
263 return horsurf;
264}
265
266/**********************************************************************/
269static int redraw_horiz(struct widget *horiz)
270{
271 int ret;
273
274 ret = (*baseclass_redraw)(horiz);
275 if (ret != 0) {
276 return ret;
277 }
278
280 get_wstate(horiz),
281 horiz->size.w);
283 horiz->size.x, horiz->size.y);
284
286
287 return ret;
288}
289
290/**********************************************************************/
302 struct gui_layer *pdest,
303 Uint16 width, Uint32 flags)
304{
305 struct widget *hor = widget_new();
306
307 hor->theme = horiz_theme;
308 hor->size.w = width;
309 hor->size.h = horiz_theme->h;
310 set_wflag(hor, WF_FREE_STRING | flags);
313 hor->mod = KMOD_NONE;
314 hor->dst = pdest;
315
316 baseclass_redraw = hor->redraw;
317 hor->redraw = redraw_horiz;
318
319 return hor;
320}
321
322/**********************************************************************/
325int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
326{
327 horiz->size.x = x;
328 horiz->size.y = y;
329 horiz->gfx = crop_rect_from_surface(horiz->dst->surface, &horiz->size);
330
331 return redraw_horiz(horiz);
332}
333
334/* =================================================== */
335/* ===================== ================== */
336/* =================================================== */
337
338/**********************************************************************/
341static int get_step(struct scroll_bar *scroll)
342{
343 float step = scroll->max - scroll->min;
344
345 step *= (float) (1.0 - (float) (scroll->active * scroll->step) /
346 (float)scroll->count);
347 step /= (float)(scroll->count - scroll->active * scroll->step);
348 step *= (float)scroll->step;
349 step++;
350
351 return (int)step;
352}
353
354/**********************************************************************/
357static int get_position(struct advanced_dialog *dlg)
358{
359 struct widget *buf = dlg->active_widget_list;
360 int count = dlg->scroll->active * dlg->scroll->step - 1;
361 int step = get_step(dlg->scroll);
362
363 /* find last seen widget */
364 while (count) {
365 if (buf == dlg->begin_active_widget_list) {
366 break;
367 }
368 count--;
369 buf = buf->prev;
370 }
371
372 count = 0;
373 if (buf != dlg->begin_active_widget_list) {
374 do {
375 count++;
376 buf = buf->prev;
377 } while (buf != dlg->begin_active_widget_list);
378 }
379
380 if (dlg->scroll->pscroll_bar) {
381 return dlg->scroll->max - dlg->scroll->pscroll_bar->size.h -
382 count * (float)step / dlg->scroll->step;
383 } else {
384 return dlg->scroll->max - count * (float)step / dlg->scroll->step;
385 }
386}
387
388/**************************************************************************
389 Vertical scroll_bar
390**************************************************************************/
391
392static struct widget *up_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 *down_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
402static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
403 struct widget *begin_active_widget_list,
404 struct widget *begin_widget_list,
405 struct widget *end_widget_list);
406
407/**********************************************************************/
410static int std_up_advanced_dlg_callback(struct widget *pwidget)
411{
413 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
414 struct widget *begin = up_scroll_widget_list(
415 dlg->scroll,
419
420 if (begin) {
421 dlg->active_widget_list = begin;
422 }
423
425 selected_widget = pwidget;
426 set_wstate(pwidget, FC_WS_SELECTED);
427 widget_redraw(pwidget);
428 widget_flush(pwidget);
429 }
430
431 return -1;
432}
433
434/**********************************************************************/
437static int std_down_advanced_dlg_callback(struct widget *pwidget)
438{
440 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
441 struct widget *begin = down_scroll_widget_list(
442 dlg->scroll,
446
447 if (begin) {
448 dlg->active_widget_list = begin;
449 }
450
452 selected_widget = pwidget;
453 set_wstate(pwidget, FC_WS_SELECTED);
454 widget_redraw(pwidget);
455 widget_flush(pwidget);
456 }
457
458 return -1;
459}
460
461/**********************************************************************/
464static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
465{
467 struct advanced_dialog *dlg = pscroll_bar->private_data.adv_dlg;
468 struct widget *begin = vertic_scroll_widget_list(
469 dlg->scroll,
473
474 if (begin) {
475 dlg->active_widget_list = begin;
476 }
477
479 set_wstate(pscroll_bar, FC_WS_SELECTED);
480 selected_widget = pscroll_bar;
481 redraw_vert(pscroll_bar);
482 widget_flush(pscroll_bar);
483 }
484
485 return -1;
486}
487
488/**********************************************************************/
492 Uint8 step, Uint8 active,
494{
495 Uint16 count = 0;
496 struct widget *buf = NULL, *pwindow = NULL;
497
498 fc_assert_ret_val(dlg != NULL, 0);
499
500 pwindow = dlg->end_widget_list;
501
502 if (!dlg->scroll) {
503 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
504
506 while (buf && (buf != dlg->begin_active_widget_list->prev)) {
507 buf = buf->prev;
508 count++;
509 }
510
511 dlg->scroll->count = count;
512 }
513
514 dlg->scroll->active = active;
515 dlg->scroll->step = step;
516
517 if (create_buttons) {
518 /* create up button */
519 buf = create_themeicon_button(current_theme->up_icon, pwindow->dst,
521
522 buf->id = ID_BUTTON;
523 buf->private_data.adv_dlg = dlg;
526
527 dlg->scroll->up_left_button = buf;
529 dlg->begin_widget_list = buf;
530
531 count = buf->size.w;
532
533 /* create down button */
534 buf = create_themeicon_button(current_theme->down_icon, pwindow->dst,
536
537 buf->id = ID_BUTTON;
538 buf->private_data.adv_dlg = dlg;
541
544 dlg->begin_widget_list = buf;
545 }
546
547 if (create_scrollbar) {
548 /* create vscrollbar */
549 buf = create_vertical(current_theme->vertic, pwindow->dst,
551
552 buf->id = ID_SCROLLBAR;
553 buf->private_data.adv_dlg = dlg;
556
557 dlg->scroll->pscroll_bar = buf;
559 dlg->begin_widget_list = buf;
560
561 if (!count) {
562 count = buf->size.w;
563 }
564 }
565
566 return count;
567}
568
569/**********************************************************************/
573 Sint16 start_x, Sint16 start_y,
575{
576 bool buttons_exist;
577
578 fc_assert_ret(scroll != NULL);
579
580 buttons_exist = (scroll->down_right_button && scroll->up_left_button);
581
582 if (buttons_exist) {
583 /* up */
584 scroll->up_left_button->size.y = start_y;
585 if (swap_start_x) {
586 scroll->up_left_button->size.x = start_x -
587 scroll->up_left_button->size.w;
588 } else {
589 scroll->up_left_button->size.x = start_x;
590 }
591 scroll->min = start_y + scroll->up_left_button->size.h;
592 /* -------------------------- */
593 /* down */
594 scroll->down_right_button->size.y = start_y + height -
595 scroll->down_right_button->size.h;
596 if (swap_start_x) {
597 scroll->down_right_button->size.x = start_x -
598 scroll->down_right_button->size.w;
599 } else {
600 scroll->down_right_button->size.x = start_x;
601 }
602 scroll->max = scroll->down_right_button->size.y;
603 }
604 /* --------------- */
605 /* scrollbar */
606 if (scroll->pscroll_bar) {
607 if (swap_start_x) {
608 scroll->pscroll_bar->size.x = start_x - scroll->pscroll_bar->size.w + 2;
609 } else {
610 scroll->pscroll_bar->size.x = start_x;
611 }
612
613 if (buttons_exist) {
614 scroll->pscroll_bar->size.y = start_y +
615 scroll->up_left_button->size.h;
616 if (scroll->count > scroll->active * scroll->step) {
617 scroll->pscroll_bar->size.h = scrollbar_size(scroll);
618 } else {
619 scroll->pscroll_bar->size.h = scroll->max - scroll->min;
620 }
621 } else {
622 scroll->pscroll_bar->size.y = start_y;
623 scroll->pscroll_bar->size.h = height;
624 scroll->min = start_y;
625 scroll->max = start_y + height;
626 }
627 }
628}
629
630/* =================================================== */
631/* ============ Vertical Scroll Group List =========== */
632/* =================================================== */
633
634/**********************************************************************/
638static struct widget *vertical_scroll_widget_list(struct widget *active_widget_list,
639 struct widget *begin_widget_list,
640 struct widget *end_widget_list,
641 int active, int step, int dir)
642{
643 struct widget *begin = active_widget_list;
644 struct widget *buf = active_widget_list;
645 struct widget *tmp = NULL;
646 int count = active; /* row */
647 int count_step = step; /* col */
648
649 if (dir < 0) {
650 /* up */
651 bool real = TRUE;
652
653 if (buf != end_widget_list) {
654 /*
655 move pointers to positions and unhide scrolled widgets
656 B = buf - new top
657 T = tmp - current top == active_widget_list
658 [B] [ ] [ ]
659 -----------
660 [T] [ ] [ ]
661 [ ] [ ] [ ]
662 -----------
663 [ ] [ ] [ ]
664 */
665 tmp = buf; /* now buf == active_widget_list == current Top */
666 while (count_step > 0) {
667 buf = buf->next;
669 count_step--;
670 }
672
673 /* setup new ActiveWidget pointer */
674 begin = buf;
675
676 /*
677 scroll pointers up
678 B = buf
679 T = tmp
680 [B0] [B1] [B2]
681 -----------
682 [T0] [T1] [T2] => B position = T position
683 [T3] [T4] [T5]
684 -----------
685 [ ] [ ] [ ]
686
687 start from B0 and go down list
688 B0 = T0, B1 = T1, B2 = T2
689 T0 = T3, T1 = T4, T2 = T5
690 etc...
691 */
692
693 /* buf == begin == new top widget */
694
695 while (count > 0) {
696 if (real) {
697 buf->size.x = tmp->size.x;
698 buf->size.y = tmp->size.y;
699 buf->gfx = tmp->gfx;
700
701 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
706 }
707 }
708
709 tmp->gfx = NULL;
710
711 if (count == 1) {
713 }
714 if (tmp == begin_widget_list) {
715 real = FALSE;
716 }
717 tmp = tmp->prev;
718 } else {
719 /*
720 unsymmetric list support.
721 This is big problem because we can't take position from unexisting
722 list member. We must put here some hypothetical positions
723
724 [B0] [B1] [B2]
725 --------------
726 [T0] [T1]
727
728 */
729 if (active > 1) {
730 /* this works well if active > 1 but is buggy when active == 1 */
731 buf->size.y += buf->size.h;
732 } else {
733 /* this works well if active == 1 but may be broken if "next"
734 element has other "y" position */
735 buf->size.y = buf->next->size.y;
736 }
737 buf->gfx = NULL;
738 }
739
740 buf = buf->prev;
741 count_step--;
742 if (!count_step) {
744 count--;
745 }
746 }
747 }
748 } else {
749 /* down */
750 count = active * step; /* row * col */
751
752 /*
753 find end
754 B = buf
755 A - start (buf == active_widget_list)
756 [ ] [ ] [ ]
757 -----------
758 [A] [ ] [ ]
759 [ ] [ ] [ ]
760 -----------
761 [B] [ ] [ ]
762 */
763 while (count && buf != begin_widget_list->prev) {
764 buf = buf->prev;
765 count--;
766 }
767
768 if (!count && buf != begin_widget_list->prev) {
769 /*
770 move pointers to positions and unhide scrolled widgets
771 B = buf
772 T = tmp
773 A - start (active_widget_list)
774 [ ] [ ] [ ]
775 -----------
776 [A] [ ] [ ]
777 [ ] [ ] [T]
778 -----------
779 [ ] [ ] [B]
780 */
781 tmp = buf->next;
782 count_step = step - 1;
783 while (count_step && buf != begin_widget_list) {
785 buf = buf->prev;
786 count_step--;
787 }
789
790 /*
791 Unsymmetric list support.
792 correct tmp and undraw empty fields
793 B = buf
794 T = tmp
795 A - start (active_widget_list)
796 [ ] [ ] [ ]
797 -----------
798 [A] [ ] [ ]
799 [ ] [T] [U] <- undraw U
800 -----------
801 [ ] [B]
802 */
803 count = count_step;
804 while (count) {
805 /* hack - clear area under unexisting list members */
808 FREESURFACE(tmp->gfx);
809 if (active == 1) {
811 }
812 tmp = tmp->next;
813 count--;
814 }
815
816 /* reset counters */
817 count = active;
818 if (count_step) {
820 } else {
822 }
823
824 /*
825 scroll pointers down
826 B = buf
827 T = tmp
828 [ ] [ ] [ ]
829 -----------
830 [ ] [ ] [ ]
831 [T2] [T1] [T0] => B position = T position
832 -----------
833 [B2] [B1] [B0]
834 */
835 while (count) {
836 buf->size.x = tmp->size.x;
837 buf->size.y = tmp->size.y;
838 buf->gfx = tmp->gfx;
839
840 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
845 }
846 }
847
848 tmp->gfx = NULL;
849
850 if (count == 1) {
852 }
853
854 tmp = tmp->next;
855 buf = buf->next;
856 count_step--;
857 if (!count_step) {
859 count--;
860 }
861 }
862 /* setup new ActiveWidget pointer */
863 begin = buf->prev;
864 }
865 }
866
867 return begin;
868}
869
870/**********************************************************************/
874{
875 struct UP_DOWN *down = (struct UP_DOWN *)data;
876
877 if (down->end != down->begin_widget_list) {
878 if (down->vscroll->pscroll_bar
879 && down->vscroll->pscroll_bar->size.y <=
880 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
881
882 /* draw bcgd */
885
886 if (down->vscroll->pscroll_bar->size.y + down->step >
887 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
888 down->vscroll->pscroll_bar->size.y =
889 down->vscroll->max - down->vscroll->pscroll_bar->size.h;
890 } else {
891 down->vscroll->pscroll_bar->size.y += down->step;
892 }
893 }
894
897 down->vscroll->active, down->vscroll->step, 1);
898
899 down->end = down->end->prev;
900
902
903 if (down->vscroll->pscroll_bar) {
904 /* Redraw scrollbar */
907 }
909
911 }
912
913 flush_dirty();
914 }
915}
916
917/**********************************************************************/
920static void inside_scroll_up_loop(void *data)
921{
922 struct UP_DOWN *up = (struct UP_DOWN *)data;
923
924 if (up && up->begin != up->end_widget_list) {
925
926 if (up->vscroll->pscroll_bar
927 && (up->vscroll->pscroll_bar->size.y >= up->vscroll->min)) {
928
929 /* draw bcgd */
932
933 if (((up->vscroll->pscroll_bar->size.y - up->step) < up->vscroll->min)) {
934 up->vscroll->pscroll_bar->size.y = up->vscroll->min;
935 } else {
936 up->vscroll->pscroll_bar->size.y -= up->step;
937 }
938 }
939
942 up->vscroll->active, up->vscroll->step, -1);
943
945
946 if (up->vscroll->pscroll_bar) {
947 /* Redraw scrollbar */
950 }
953 }
954
955 flush_dirty();
956 }
957}
958
959/**********************************************************************/
962static Uint16 scroll_mouse_motion_handler(SDL_MouseMotionEvent *motion_event,
963 void *data)
964{
965 struct UP_DOWN *motion = (struct UP_DOWN *)data;
966 int yrel;
967 int y;
968 int normalized_y;
969 int net_slider_area;
970 int net_count;
971 float scroll_step;
972
973 yrel = motion_event->y - motion->prev_y;
974 motion->prev_x = motion_event->x;
975 motion->prev_y = motion_event->y;
976
977 y = motion_event->y - motion->vscroll->pscroll_bar->dst->dest_rect.y;
978
979 normalized_y = (y - motion->offset);
980
981 net_slider_area = (motion->vscroll->max - motion->vscroll->min - motion->vscroll->pscroll_bar->size.h);
982 net_count = round((float)motion->vscroll->count / motion->vscroll->step) - motion->vscroll->active + 1;
983 scroll_step = (float)net_slider_area / net_count;
984
985 if ((yrel != 0)
986 && ((normalized_y >= motion->vscroll->min)
987 || ((normalized_y < motion->vscroll->min)
988 && (motion->vscroll->pscroll_bar->size.y > motion->vscroll->min)))
989 && ((normalized_y <= motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)
990 || ((normalized_y > motion->vscroll->max)
991 && (motion->vscroll->pscroll_bar->size.y < (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)))) ) {
992 int count;
993
994 /* Draw bcgd */
997
998 if ((motion->vscroll->pscroll_bar->size.y + yrel) >
999 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)) {
1000
1001 motion->vscroll->pscroll_bar->size.y =
1002 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h);
1003
1004 } else if ((motion->vscroll->pscroll_bar->size.y + yrel) < motion->vscroll->min) {
1005 motion->vscroll->pscroll_bar->size.y = motion->vscroll->min;
1006 } else {
1007 motion->vscroll->pscroll_bar->size.y += yrel;
1008 }
1009
1010 count = round((motion->vscroll->pscroll_bar->size.y - motion->old_y) / scroll_step);
1011
1012 if (count != 0) {
1013 int i = count;
1014
1015 while (i != 0) {
1016 motion->begin = vertical_scroll_widget_list(motion->begin,
1017 motion->begin_widget_list,
1018 motion->end_widget_list,
1019 motion->vscroll->active,
1020 motion->vscroll->step, i);
1021 if (i > 0) {
1022 i--;
1023 } else {
1024 i++;
1025 }
1026 } /* while (i != 0) */
1027
1028 motion->old_y = motion->vscroll->min +
1029 ((round((motion->old_y - motion->vscroll->min) / scroll_step) + count) * scroll_step);
1030
1032 }
1033
1034 /* Redraw slider */
1037 }
1040
1041 flush_dirty();
1042 }
1043
1044 return ID_ERROR;
1045}
1046
1047/**********************************************************************/
1050static Uint16 scroll_mouse_button_up(SDL_MouseButtonEvent *button_event,
1051 void *data)
1052{
1053 return (Uint16)ID_SCROLLBAR;
1054}
1055
1056/**********************************************************************/
1059static struct widget *down_scroll_widget_list(struct scroll_bar *vscroll,
1060 struct widget *begin_active_widget_list,
1061 struct widget *begin_widget_list,
1062 struct widget *end_widget_list)
1063{
1064 struct UP_DOWN down;
1065 struct widget *begin = begin_active_widget_list;
1066 int step = vscroll->active * vscroll->step - 1;
1067
1068 while (step--) {
1069 begin = begin->prev;
1070 }
1071
1072 down.step = get_step(vscroll);
1073 down.begin = begin_active_widget_list;
1074 down.end = begin;
1075 down.begin_widget_list = begin_widget_list;
1076 down.end_widget_list = end_widget_list;
1077 down.vscroll = vscroll;
1078
1081
1082 return down.begin;
1083}
1084
1085/**********************************************************************/
1088static struct widget *up_scroll_widget_list(struct scroll_bar *vscroll,
1089 struct widget *begin_active_widget_list,
1090 struct widget *begin_widget_list,
1091 struct widget *end_widget_list)
1092{
1093 struct UP_DOWN up;
1094
1095 up.step = get_step(vscroll);
1096 up.begin = begin_active_widget_list;
1099 up.vscroll = vscroll;
1100
1101 gui_event_loop((void *)&up, inside_scroll_up_loop, NULL, NULL, NULL,
1102 NULL, NULL, NULL, NULL, scroll_mouse_button_up, NULL);
1103
1104 return up.begin;
1105}
1106
1107/**********************************************************************/
1110static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
1111 struct widget *begin_active_widget_list,
1112 struct widget *begin_widget_list,
1113 struct widget *end_widget_list)
1114{
1115 struct UP_DOWN motion;
1116
1117 motion.step = get_step(vscroll);
1118 motion.begin = begin_active_widget_list;
1121 motion.vscroll = vscroll;
1122 motion.old_y = vscroll->pscroll_bar->size.y;
1123 SDL_GetMouseState(&motion.prev_x, &motion.prev_y);
1124 motion.offset = motion.prev_y - vscroll->pscroll_bar->dst->dest_rect.y - vscroll->pscroll_bar->size.y;
1125
1126 MOVE_STEP_X = 0;
1127 MOVE_STEP_Y = 3;
1128 /* Filter mouse motion events */
1129 SDL_SetEventFilter(FilterMouseMotionEvents, NULL);
1130 gui_event_loop((void *)&motion, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1132 /* Turn off Filter mouse motion events */
1133 SDL_SetEventFilter(NULL, NULL);
1136
1137 return motion.begin;
1138}
1139
1140/* ==================================================================== */
1141
1142/**********************************************************************/
1152 struct widget *new_widget,
1153 struct widget *add_dock,
1154 bool dir,
1155 Sint16 start_x, Sint16 start_y)
1156{
1157 struct widget *buf = NULL;
1158 struct widget *end = NULL, *old_end = NULL;
1159 bool last = FALSE, seen = TRUE;
1160
1161 fc_assert_ret_val(dlg != NULL, FALSE);
1163
1164 if (!add_dock) {
1165 add_dock = dlg->begin_widget_list; /* Last item */
1166 }
1167
1168 dlg->scroll->count++;
1169
1170 if (dlg->scroll->count > (dlg->scroll->active * dlg->scroll->step)) {
1171 /* -> Scrollbar needed */
1172
1173 if (dlg->active_widget_list) {
1174 /* -> Scrollbar is already visible */
1175 int i = 0;
1176
1177 /* Find last active widget */
1178 old_end = add_dock;
1179 while (old_end != dlg->active_widget_list) {
1180 old_end = old_end->next;
1181 i++;
1182 if (old_end == dlg->end_active_widget_list) {
1183 /* Implies (old_end == dlg->active_widget_list)? */
1184 seen = FALSE;
1185 break;
1186 }
1187 }
1188
1189 if (seen) {
1190 int count = (dlg->scroll->active * dlg->scroll->step) - 1;
1191
1192 if (i > count) {
1193 seen = FALSE;
1194 } else {
1195 while (count > 0) {
1196 old_end = old_end->prev;
1197 count--;
1198 }
1199 if (old_end == add_dock) {
1200 last = TRUE;
1201 }
1202 }
1203 }
1204
1205 } else {
1206 last = TRUE;
1208 show_scrollbar(dlg->scroll);
1209 }
1210 }
1211
1212 /* Add pointer to list */
1213 if (dir) {
1214 /* Upper add */
1216
1217 if (add_dock == dlg->end_widget_list) {
1219 }
1220 if (add_dock == dlg->end_active_widget_list) {
1222 }
1223 if (add_dock == dlg->active_widget_list) {
1225 }
1226 } else {
1227 /* Down add */
1229
1230 if (add_dock == dlg->begin_widget_list) {
1232 }
1233
1234 if (add_dock == dlg->begin_active_widget_list) {
1236 }
1237 }
1238
1239 /* Setup draw positions */
1240 if (seen) {
1241 if (!dlg->begin_active_widget_list) {
1242 /* First element ( active list empty ) */
1243 fc_assert_msg(!dir, "Forbidden List Operation");
1244
1245 new_widget->size.x = start_x;
1246 new_widget->size.y = start_y;
1249 if (!dlg->begin_widget_list) {
1252 }
1253 } else {
1254 /* There are some elements on local active list */
1255 if (last) {
1256 /* We add to last seen position */
1257 if (dir) {
1258 /* Only swap add_dock with new_widget on last seen positions */
1259 new_widget->size.x = add_dock->size.x;
1260 new_widget->size.y = add_dock->size.y;
1261 new_widget->gfx = add_dock->gfx;
1262 add_dock->gfx = NULL;
1264 } else {
1265 /* Reposition all widgets */
1266 buf = new_widget;
1267 do {
1268 buf->size.x = buf->next->size.x;
1269 buf->size.y = buf->next->size.y;
1270 buf->gfx = buf->next->gfx;
1271 buf->next->gfx = NULL;
1272 buf = buf->next;
1273 } while (buf != dlg->active_widget_list);
1274 buf->gfx = NULL;
1277 }
1278 } else { /* !last */
1279 buf = new_widget;
1280 /* Find last seen widget */
1281 if (dlg->active_widget_list) {
1282 int count = dlg->scroll->active * dlg->scroll->step - 1;
1283
1284 end = dlg->active_widget_list;
1285 while (count && end != dlg->begin_active_widget_list) {
1286 end = end->prev;
1287 count--;
1288 }
1289 }
1290 while (buf) {
1291 if (buf == dlg->begin_active_widget_list) {
1292 struct widget *tmp = buf;
1293 int count = dlg->scroll->step;
1294
1295 while (count) {
1296 tmp = tmp->next;
1297 count--;
1298 }
1299 buf->size.x = tmp->size.x;
1300 buf->size.y = tmp->size.y + tmp->size.h;
1301 /* Break when last active widget or last seen widget */
1302 break;
1303 } else {
1304 buf->size.x = buf->prev->size.x;
1305 buf->size.y = buf->prev->size.y;
1306 buf->gfx = buf->prev->gfx;
1307 buf->prev->gfx = NULL;
1308 if (buf == end) {
1309 break;
1310 }
1311 }
1312 buf = buf->prev;
1313 }
1314 if (old_end && buf->prev == old_end) {
1316 }
1317 } /* !last */
1318 } /* dlg->begin_active_widget_list */
1319 } else {
1320 /* Not seen */
1322 }
1323
1324 if (dlg->active_widget_list && dlg->scroll->pscroll_bar) {
1327
1328 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1329 if (last) {
1330 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1331 }
1334 }
1335 if (!seen) {
1337 }
1338 }
1339
1340 return last;
1341}
1342
1343/**********************************************************************/
1350 struct widget *pwidget)
1351{
1352 struct widget *buf = pwidget;
1353
1354 fc_assert_ret_val(dlg != NULL, FALSE);
1355
1356 /* If begin == end -> size = 1 */
1358
1359 if (dlg->scroll) {
1360 dlg->scroll->count = 0;
1361 }
1362
1365 }
1366
1367 if (dlg->end_active_widget_list == dlg->end_widget_list) {
1369 }
1370
1372 dlg->active_widget_list = NULL;
1374
1375 widget_undraw(pwidget);
1376 widget_mark_dirty(pwidget);
1377 del_widget_from_gui_list(pwidget);
1378
1379 return FALSE;
1380 }
1381
1382 if (dlg->scroll && dlg->active_widget_list) {
1383 /* Scrollbar exist and active, start mod. from last seen label */
1384 struct widget *last;
1385 bool widget_found = FALSE;
1386 int count;
1387
1388 /* This is always true because no-scrolbar case (active * step < count)
1389 will be supported in other part of code (see "else" part) */
1390 count = dlg->scroll->active * dlg->scroll->step;
1391
1392 /* Find last */
1393 buf = dlg->active_widget_list;
1394 while (count > 0) {
1395 buf = buf->prev;
1396 count--;
1397 }
1398 if (!buf) {
1399 last = dlg->begin_active_widget_list;
1400 } else {
1401 last = buf->next;
1402 }
1403
1404 if (last == dlg->begin_active_widget_list) {
1405 if (dlg->scroll->step == 1) {
1408
1409 /* Look for the widget in the non-visible part */
1411 while (buf != dlg->active_widget_list) {
1412 if (buf == pwidget) {
1414 buf = dlg->active_widget_list;
1415 break;
1416 }
1417 buf = buf->prev;
1418 }
1419
1420 /* If we haven't found it yet, look in the visible part and update the
1421 * positions of the other widgets */
1422 if (!widget_found) {
1423 while (buf != pwidget) {
1424 buf->gfx = buf->prev->gfx;
1425 buf->prev->gfx = NULL;
1426 buf->size.x = buf->prev->size.x;
1427 buf->size.y = buf->prev->size.y;
1428 buf = buf->prev;
1429 }
1430 }
1431 } else {
1432 buf = last;
1433 /* Undraw last widget */
1436 FREESURFACE(buf->gfx);
1437 goto std;
1438 }
1439 } else {
1441
1442std: while (buf != pwidget) {
1443 buf->gfx = buf->next->gfx;
1444 buf->next->gfx = NULL;
1445 buf->size.x = buf->next->size.x;
1446 buf->size.y = buf->next->size.y;
1447 buf = buf->next;
1448 }
1449 }
1450
1451 if ((dlg->scroll->count - 1) <= (dlg->scroll->active * dlg->scroll->step)) {
1452 /* Scrollbar not needed anymore */
1453 hide_scrollbar(dlg->scroll);
1454 dlg->active_widget_list = NULL;
1455 }
1456 dlg->scroll->count--;
1457
1458 if (dlg->active_widget_list) {
1459 if (dlg->scroll->pscroll_bar) {
1461 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1463 }
1464 }
1465
1466 } else {
1467 /* No scrollbar */
1469
1470 /* Undraw last widget */
1473 FREESURFACE(buf->gfx);
1474
1475 while (buf != pwidget) {
1476 buf->gfx = buf->next->gfx;
1477 buf->next->gfx = NULL;
1478 buf->size.x = buf->next->size.x;
1479 buf->size.y = buf->next->size.y;
1480 buf = buf->next;
1481 }
1482
1483 if (dlg->scroll) {
1484 dlg->scroll->count--;
1485 }
1486 }
1487
1488 if (pwidget == dlg->begin_widget_list) {
1489 dlg->begin_widget_list = pwidget->next;
1490 }
1491
1492 if (pwidget == dlg->begin_active_widget_list) {
1493 dlg->begin_active_widget_list = pwidget->next;
1494 }
1495
1496 if (pwidget == dlg->end_active_widget_list) {
1497 if (pwidget == dlg->end_widget_list) {
1498 dlg->end_widget_list = pwidget->prev;
1499 }
1500
1501 if (pwidget == dlg->active_widget_list) {
1502 dlg->active_widget_list = pwidget->prev;
1503 }
1504
1505 dlg->end_active_widget_list = pwidget->prev;
1506
1507 }
1508
1509 if (dlg->active_widget_list && (dlg->active_widget_list == pwidget)) {
1510 dlg->active_widget_list = pwidget->prev;
1511 }
1512
1513 del_widget_from_gui_list(pwidget);
1514
1515 if (dlg->scroll && dlg->scroll->pscroll_bar && dlg->active_widget_list) {
1517 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1519 }
1520
1521 return TRUE;
1522}
1523
1524/**********************************************************************/
1528{
1529 fc_assert_ret(scroll != NULL);
1530
1531 if (scroll->up_left_button) {
1533 }
1534 if (scroll->down_right_button) {
1536 }
1537 if (scroll->pscroll_bar) {
1539 }
1540}
1541
1542/**************************************************************************
1543 Horizontal Scrollbar
1544**************************************************************************/
1545
1546
1547/**********************************************************************/
1551 Sint16 start_x, Sint16 start_y,
1552 Uint16 width, Uint16 active,
1554 bool swap_start_y)
1555{
1556 Uint16 count = 0;
1557 struct widget *buf = NULL, *pwindow = NULL;
1558
1559 fc_assert_ret_val(dlg != NULL, 0);
1560
1561 pwindow = dlg->end_widget_list;
1562
1563 if (!dlg->scroll) {
1564 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
1565
1566 dlg->scroll->active = active;
1567
1569 while (buf && buf != dlg->begin_active_widget_list->prev) {
1570 buf = buf->prev;
1571 count++;
1572 }
1573
1574 dlg->scroll->count = count;
1575 }
1576
1577 if (create_buttons) {
1578 /* create up button */
1579 buf = create_themeicon_button(current_theme->left_icon, pwindow->dst, NULL, 0);
1580
1581 buf->id = ID_BUTTON;
1582 buf->data.ptr = (void *)dlg;
1584
1585 buf->size.x = start_x;
1586 if (swap_start_y) {
1587 buf->size.y = start_y - buf->size.h;
1588 } else {
1589 buf->size.y = start_y;
1590 }
1591
1592 dlg->scroll->min = start_x + buf->size.w;
1593 dlg->scroll->up_left_button = buf;
1595 dlg->begin_widget_list = buf;
1596
1597 count = buf->size.h;
1598
1599 /* create down button */
1600 buf = create_themeicon_button(current_theme->right_icon, pwindow->dst, NULL, 0);
1601
1602 buf->id = ID_BUTTON;
1603 buf->data.ptr = (void *)dlg;
1605
1606 buf->size.x = start_x + width - buf->size.w;
1607 if (swap_start_y) {
1608 buf->size.y = start_y - buf->size.h;
1609 } else {
1610 buf->size.y = start_y;
1611 }
1612
1613 dlg->scroll->max = buf->size.x;
1616 dlg->begin_widget_list = buf;
1617 }
1618
1619 if (create_scrollbar) {
1620 /* create vscrollbar */
1621 buf = create_horizontal(current_theme->horiz, pwindow->dst,
1623
1624 buf->id = ID_SCROLLBAR;
1625 buf->data.ptr = (void *)dlg;
1627
1628 if (swap_start_y) {
1629 buf->size.y = start_y - buf->size.h;
1630 } else {
1631 buf->size.y = start_y;
1632 }
1633
1634 if (create_buttons) {
1635 buf->size.x = start_x + dlg->scroll->up_left_button->size.w;
1636 if (dlg->scroll->count > dlg->scroll->active) {
1637 buf->size.w = scrollbar_size(dlg->scroll);
1638 } else {
1639 buf->size.w = dlg->scroll->max - dlg->scroll->min;
1640 }
1641 } else {
1642 buf->size.x = start_x;
1643 dlg->scroll->min = start_x;
1644 dlg->scroll->max = start_x + width;
1645 }
1646
1647 dlg->scroll->pscroll_bar = buf;
1649 dlg->begin_widget_list = buf;
1650
1651 if (!count) {
1652 count = buf->size.h;
1653 }
1654 }
1655
1656 return count;
1657}
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
QString current_theme
Definition fc_client.cpp:65
void flush_dirty(void)
Definition mapview.c:450
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
int FilterMouseMotionEvents(void *data, SDL_Event *event)
Definition gui_main.c:572
int MOVE_STEP_Y
Definition gui_main.c:101
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)(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:593
int MOVE_STEP_X
Definition gui_main.c:100
struct widget * selected_widget
Definition widget.c:48
#define adj_size(size)
Definition gui_main.h:138
#define DEFAULT_MOVE_STEP
Definition gui_main.h:110
#define PRESSED_EVENT(event)
Definition gui_main.h:68
@ ID_ERROR
Definition gui_id.h:26
@ ID_BUTTON
Definition gui_id.h:29
@ ID_SCROLLBAR
Definition gui_id.h:32
#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 widget * end_widget_list
struct widget * begin_widget_list
struct scroll_bar * vscroll
struct widget * begin
struct widget * end
struct widget * active_widget_list
Definition widget.h:186
struct widget * end_widget_list
Definition widget.h:182
struct widget * begin_widget_list
Definition widget.h:181
struct widget * begin_active_widget_list
Definition widget.h:184
struct widget * end_active_widget_list
Definition widget.h:185
struct scroll_bar * scroll
Definition widget.h:187
SDL_Surface * surface
Definition graphics.h:229
SDL_Rect dest_rect
Definition graphics.h:228
struct widget * up_left_button
struct widget * pscroll_bar
struct widget * down_right_button
SDL_Event event
Definition graphics.h:217
struct widget * next
Definition widget.h:113
union widget::@214 data
struct gui_layer * dst
Definition widget.h:116
SDL_Surface * gfx
Definition widget.h:120
struct widget * prev
Definition widget.h:114
int(* action)(struct widget *)
Definition widget.h:157
struct container * cont
Definition widget.h:127
union widget::@215 private_data
struct advanced_dialog * adv_dlg
Definition widget.h:139
SDL_Surface * theme
Definition widget.h:118
SDL_Rect size
Definition widget.h:145
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
void refresh_widget_background(struct widget *pwidget)
Definition widget.c:1150
void unselect_widget_action(void)
Definition widget.c:417
void widget_add_as_prev(struct widget *new_widget, struct widget *add_dock)
Definition widget.c:601
Uint16 redraw_group(const struct widget *begin_group_widget_list, const struct widget *end_group_widget_list, int add_to_update)
Definition widget.c:719
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 SDL_Surface * create_horizontal_surface(SDL_Surface *horiz_theme, Uint8 state, Uint16 width)
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)
#define hide_scrollbar(scrollbar)
#define show_scrollbar(scrollbar)
#define scrollbar_size(scroll)