Freeciv-3.3: /fast/freeciv/nightly/main/client/gui-sdl3/widget_scrollbar.c Source File

Freeciv-3.3

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