Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-sdl2/widget_scrollbar.c Source File

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
39 struct UP_DOWN {
40 struct widget *begin;
41 struct widget *end;
42 struct widget *begin_widget_list;
43 struct widget *end_widget_list;
44 struct scroll_bar *vscroll;
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
62 static int (*baseclass_redraw)(struct widget *pwidget);
63
64/* =================================================== */
65/* ===================== VSCROLLBAR ================== */
66/* =================================================== */
67
68/**********************************************************************/
74 static SDL_Surface *create_vertical_surface(SDL_Surface *vert_theme,
75 enum widget_state state,
76 Uint16 height)
77{
78 SDL_Surface *versurf = NULL;
79 SDL_Rect src, des;
80 Uint16 i;
81 Uint16 start_y;
82 Uint16 tile_count_midd;
83 Uint8 tile_len_end;
84 Uint8 tile_len_midd;
85
86 tile_len_end = vert_theme->h / 16;
87
88 start_y = 0 + state * (vert_theme->h / 4);
89
90 tile_len_midd = vert_theme->h / 4 - tile_len_end * 2;
91
92 tile_count_midd = (height - tile_len_end * 2) / tile_len_midd;
93
94 /* Correction */
95 if (tile_len_midd * tile_count_midd + tile_len_end * 2 < height) {
96 tile_count_midd++;
97 }
98
99 if (!tile_count_midd) {
100 versurf = create_surf(vert_theme->w, tile_len_end * 2, SDL_SWSURFACE);
101 } else {
102 versurf = create_surf(vert_theme->w, height, SDL_SWSURFACE);
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++) {
117 des.y = tile_len_end + i * tile_len_midd;
118 alphablit(vert_theme, &src, versurf, &des, 255);
119 }
120
121 src.y = start_y + tile_len_end + tile_len_midd;
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/**********************************************************************/
132 static int redraw_vert(struct widget *vert)
133{
134 int ret;
135 SDL_Surface *vert_surf;
136
137 ret = (*baseclass_redraw)(vert);
138 if (ret != 0) {
139 return ret;
140 }
141
142 vert_surf = create_vertical_surface(vert->theme,
143 get_wstate(vert),
144 vert->size.h);
145 ret = blit_entire_src(vert_surf, vert->dst->surface,
146 vert->size.x, vert->size.y);
147
148 FREESURFACE(vert_surf);
149
150 return ret;
151}
152
153/**********************************************************************/
164 struct widget *create_vertical(SDL_Surface *vert_theme, struct gui_layer *pdest,
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;
172 set_wflag(vert, (WF_FREE_STRING | WF_FREE_GFX | flags));
173 set_wstate(vert, FC_WS_DISABLED);
174 set_wtype(vert, WT_VSCROLLBAR);
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/**********************************************************************/
187 int draw_vert(struct widget *vert, Sint16 x, Sint16 y)
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/**********************************************************************/
212 static SDL_Surface *create_horizontal_surface(SDL_Surface *horiz_theme,
213 Uint8 state, Uint16 width)
214{
215 SDL_Surface *horsurf = NULL;
216 SDL_Rect src, des;
217 Uint16 i;
218 Uint16 start_x;
219 Uint16 tile_count_midd;
220 Uint8 tile_len_end;
221 Uint8 tile_len_midd;
222
223 tile_len_end = horiz_theme->w / 16;
224
225 start_x = 0 + state * (horiz_theme->w / 4);
226
227 tile_len_midd = horiz_theme->w / 4 - tile_len_end * 2;
228
229 tile_count_midd = (width - tile_len_end * 2) / tile_len_midd;
230
231 /* Correction */
232 if (tile_len_midd * tile_count_midd + tile_len_end * 2 < width) {
233 tile_count_midd++;
234 }
235
236 if (!tile_count_midd) {
237 horsurf = create_surf(tile_len_end * 2, horiz_theme->h, SDL_SWSURFACE);
238 } else {
239 horsurf = create_surf(width, horiz_theme->h, SDL_SWSURFACE);
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++) {
254 des.x = tile_len_end + i * tile_len_midd;
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/**********************************************************************/
269 static int redraw_horiz(struct widget *horiz)
270{
271 int ret;
272 SDL_Surface *horiz_surf;
273
274 ret = (*baseclass_redraw)(horiz);
275 if (ret != 0) {
276 return ret;
277 }
278
279 horiz_surf = create_horizontal_surface(horiz->theme,
280 get_wstate(horiz),
281 horiz->size.w);
282 ret = blit_entire_src(horiz_surf, horiz->dst->surface,
283 horiz->size.x, horiz->size.y);
284
285 FREESURFACE(horiz_surf);
286
287 return ret;
288}
289
290/**********************************************************************/
301 struct widget *create_horizontal(SDL_Surface *horiz_theme,
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);
311 set_wstate(hor, FC_WS_DISABLED);
312 set_wtype(hor, WT_HSCROLLBAR);
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/**********************************************************************/
325 int 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/**********************************************************************/
341 static 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/**********************************************************************/
357 static 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/**********************************************************************/
410 static int std_up_advanced_dlg_callback(struct widget *pwidget)
411{
412 if (PRESSED_EVENT(main_data.event)) {
413 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
414 struct widget *begin = up_scroll_widget_list(
415 dlg->scroll,
416 dlg->active_widget_list,
417 dlg->begin_active_widget_list,
418 dlg->end_active_widget_list);
419
420 if (begin) {
421 dlg->active_widget_list = begin;
422 }
423
424 unselect_widget_action();
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/**********************************************************************/
437 static int std_down_advanced_dlg_callback(struct widget *pwidget)
438{
439 if (PRESSED_EVENT(main_data.event)) {
440 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
441 struct widget *begin = down_scroll_widget_list(
442 dlg->scroll,
443 dlg->active_widget_list,
444 dlg->begin_active_widget_list,
445 dlg->end_active_widget_list);
446
447 if (begin) {
448 dlg->active_widget_list = begin;
449 }
450
451 unselect_widget_action();
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/**********************************************************************/
464 static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
465{
466 if (PRESSED_EVENT(main_data.event)) {
467 struct advanced_dialog *dlg = pscroll_bar->private_data.adv_dlg;
468 struct widget *begin = vertic_scroll_widget_list(
469 dlg->scroll,
470 dlg->active_widget_list,
471 dlg->begin_active_widget_list,
472 dlg->end_active_widget_list);
473
474 if (begin) {
475 dlg->active_widget_list = begin;
476 }
477
478 unselect_widget_action();
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/**********************************************************************/
491 Uint32 create_vertical_scrollbar(struct advanced_dialog *dlg,
492 Uint8 step, Uint8 active,
493 bool create_scrollbar, bool create_buttons)
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
505 buf = dlg->end_active_widget_list;
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,
520 NULL, WF_RESTORE_BACKGROUND);
521
522 buf->id = ID_BUTTON;
523 buf->private_data.adv_dlg = dlg;
524 buf->action = std_up_advanced_dlg_callback;
525 set_wstate(buf, FC_WS_NORMAL);
526
527 dlg->scroll->up_left_button = buf;
528 widget_add_as_prev(buf, dlg->begin_widget_list);
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,
535 NULL, WF_RESTORE_BACKGROUND);
536
537 buf->id = ID_BUTTON;
538 buf->private_data.adv_dlg = dlg;
539 buf->action = std_down_advanced_dlg_callback;
540 set_wstate(buf, FC_WS_NORMAL);
541
542 dlg->scroll->down_right_button = buf;
543 widget_add_as_prev(buf, dlg->begin_widget_list);
544 dlg->begin_widget_list = buf;
545 }
546
547 if (create_scrollbar) {
548 /* create vscrollbar */
549 buf = create_vertical(current_theme->vertic, pwindow->dst,
550 adj_size(10), WF_RESTORE_BACKGROUND);
551
552 buf->id = ID_SCROLLBAR;
553 buf->private_data.adv_dlg = dlg;
554 buf->action = std_vscroll_advanced_dlg_callback;
555 set_wstate(buf, FC_WS_NORMAL);
556
557 dlg->scroll->pscroll_bar = buf;
558 widget_add_as_prev(buf, dlg->begin_widget_list);
559 dlg->begin_widget_list = buf;
560
561 if (!count) {
562 count = buf->size.w;
563 }
564 }
565
566 return count;
567}
568
569/**********************************************************************/
572 void setup_vertical_scrollbar_area(struct scroll_bar *scroll,
573 Sint16 start_x, Sint16 start_y,
574 Uint16 height, bool swap_start_x)
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/**********************************************************************/
638 static 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;
668 clear_wflag(buf, WF_HIDDEN);
669 count_step--;
670 }
671 count_step = step;
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)) {
702 widget_undraw(tmp);
703 widget_mark_dirty(tmp);
704 if (get_wflags(buf) & WF_RESTORE_BACKGROUND) {
705 refresh_widget_background(buf);
706 }
707 }
708
709 tmp->gfx = NULL;
710
711 if (count == 1) {
712 set_wflag(tmp, WF_HIDDEN);
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) {
743 count_step = 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) {
784 clear_wflag(buf, WF_HIDDEN);
785 buf = buf->prev;
786 count_step--;
787 }
788 clear_wflag(buf, WF_HIDDEN);
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 */
806 widget_undraw(tmp);
807 widget_mark_dirty(tmp);
808 FREESURFACE(tmp->gfx);
809 if (active == 1) {
810 set_wflag(tmp, WF_HIDDEN);
811 }
812 tmp = tmp->next;
813 count--;
814 }
815
816 /* reset counters */
817 count = active;
818 if (count_step) {
819 count_step = step - count_step;
820 } else {
821 count_step = step;
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)) {
841 widget_undraw(tmp);
842 widget_mark_dirty(tmp);
843 if (get_wflags(buf) & WF_RESTORE_BACKGROUND) {
844 refresh_widget_background(buf);
845 }
846 }
847
848 tmp->gfx = NULL;
849
850 if (count == 1) {
851 set_wflag(tmp, WF_HIDDEN);
852 }
853
854 tmp = tmp->next;
855 buf = buf->next;
856 count_step--;
857 if (!count_step) {
858 count_step = step;
859 count--;
860 }
861 }
862 /* setup new ActiveWidget pointer */
863 begin = buf->prev;
864 }
865 }
866
867 return begin;
868}
869
870/**********************************************************************/
873 static void inside_scroll_down_loop(void *data)
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 */
883 widget_undraw(down->vscroll->pscroll_bar);
884 widget_mark_dirty(down->vscroll->pscroll_bar);
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
895 down->begin = vertical_scroll_widget_list(down->begin,
896 down->begin_widget_list, down->end_widget_list,
897 down->vscroll->active, down->vscroll->step, 1);
898
899 down->end = down->end->prev;
900
901 redraw_group(down->begin_widget_list, down->end_widget_list, TRUE);
902
903 if (down->vscroll->pscroll_bar) {
904 /* Redraw scrollbar */
905 if (get_wflags(down->vscroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
906 refresh_widget_background(down->vscroll->pscroll_bar);
907 }
908 redraw_vert(down->vscroll->pscroll_bar);
909
910 widget_mark_dirty(down->vscroll->pscroll_bar);
911 }
912
913 flush_dirty();
914 }
915}
916
917/**********************************************************************/
920 static 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 */
930 widget_undraw(up->vscroll->pscroll_bar);
931 widget_mark_dirty(up->vscroll->pscroll_bar);
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
940 up->begin = vertical_scroll_widget_list(up->begin,
941 up->begin_widget_list, up->end_widget_list,
942 up->vscroll->active, up->vscroll->step, -1);
943
944 redraw_group(up->begin_widget_list, up->end_widget_list, TRUE);
945
946 if (up->vscroll->pscroll_bar) {
947 /* Redraw scrollbar */
948 if (get_wflags(up->vscroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
949 refresh_widget_background(up->vscroll->pscroll_bar);
950 }
951 redraw_vert(up->vscroll->pscroll_bar);
952 widget_mark_dirty(up->vscroll->pscroll_bar);
953 }
954
955 flush_dirty();
956 }
957}
958
959/**********************************************************************/
962 static 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 */
995 widget_undraw(motion->vscroll->pscroll_bar);
996 widget_mark_dirty(motion->vscroll->pscroll_bar);
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
1031 redraw_group(motion->begin_widget_list, motion->end_widget_list, TRUE);
1032 }
1033
1034 /* Redraw slider */
1035 if (get_wflags(motion->vscroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
1036 refresh_widget_background(motion->vscroll->pscroll_bar);
1037 }
1038 redraw_vert(motion->vscroll->pscroll_bar);
1039 widget_mark_dirty(motion->vscroll->pscroll_bar);
1040
1041 flush_dirty();
1042 }
1043
1044 return ID_ERROR;
1045}
1046
1047/**********************************************************************/
1050 static Uint16 scroll_mouse_button_up(SDL_MouseButtonEvent *button_event,
1051 void *data)
1052{
1053 return (Uint16)ID_SCROLLBAR;
1054}
1055
1056/**********************************************************************/
1059 static 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
1079 gui_event_loop((void *)&down, inside_scroll_down_loop, NULL, NULL, NULL,
1080 NULL, NULL, NULL, NULL, scroll_mouse_button_up, NULL);
1081
1082 return down.begin;
1083}
1084
1085/**********************************************************************/
1088 static 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;
1097 up.begin_widget_list = begin_widget_list;
1098 up.end_widget_list = end_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/**********************************************************************/
1110 static 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;
1119 motion.begin_widget_list = begin_widget_list;
1120 motion.end_widget_list = end_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,
1131 scroll_mouse_button_up, scroll_mouse_motion_handler);
1132 /* Turn off Filter mouse motion events */
1133 SDL_SetEventFilter(NULL, NULL);
1134 MOVE_STEP_X = DEFAULT_MOVE_STEP;
1135 MOVE_STEP_Y = DEFAULT_MOVE_STEP;
1136
1137 return motion.begin;
1138}
1139
1140/* ==================================================================== */
1141
1142/**********************************************************************/
1151 bool add_widget_to_vertical_scroll_widget_list(struct advanced_dialog *dlg,
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);
1162 fc_assert_ret_val(dlg->scroll != 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;
1207 dlg->active_widget_list = dlg->end_active_widget_list;
1208 show_scrollbar(dlg->scroll);
1209 }
1210 }
1211
1212 /* Add pointer to list */
1213 if (dir) {
1214 /* Upper add */
1215 widget_add_next(new_widget, add_dock);
1216
1217 if (add_dock == dlg->end_widget_list) {
1218 dlg->end_widget_list = new_widget;
1219 }
1220 if (add_dock == dlg->end_active_widget_list) {
1221 dlg->end_active_widget_list = new_widget;
1222 }
1223 if (add_dock == dlg->active_widget_list) {
1224 dlg->active_widget_list = new_widget;
1225 }
1226 } else {
1227 /* Down add */
1228 widget_add_as_prev(new_widget, add_dock);
1229
1230 if (add_dock == dlg->begin_widget_list) {
1231 dlg->begin_widget_list = new_widget;
1232 }
1233
1234 if (add_dock == dlg->begin_active_widget_list) {
1235 dlg->begin_active_widget_list = new_widget;
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;
1247 dlg->begin_active_widget_list = new_widget;
1248 dlg->end_active_widget_list = new_widget;
1249 if (!dlg->begin_widget_list) {
1250 dlg->begin_widget_list = new_widget;
1251 dlg->end_widget_list = new_widget;
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;
1263 set_wflag(add_dock, WF_HIDDEN);
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;
1275 set_wflag(buf, WF_HIDDEN);
1276 dlg->active_widget_list = dlg->active_widget_list->prev;
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) {
1315 set_wflag(old_end, WF_HIDDEN);
1316 }
1317 } /* !last */
1318 } /* dlg->begin_active_widget_list */
1319 } else {
1320 /* Not seen */
1321 set_wflag(new_widget, WF_HIDDEN);
1322 }
1323
1324 if (dlg->active_widget_list && dlg->scroll->pscroll_bar) {
1325 widget_undraw(dlg->scroll->pscroll_bar);
1326 widget_mark_dirty(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 }
1332 if (get_wflags(dlg->scroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
1333 refresh_widget_background(dlg->scroll->pscroll_bar);
1334 }
1335 if (!seen) {
1336 redraw_vert(dlg->scroll->pscroll_bar);
1337 }
1338 }
1339
1340 return last;
1341}
1342
1343/**********************************************************************/
1349 bool del_widget_from_vertical_scroll_widget_list(struct advanced_dialog *dlg,
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 */
1357 if (dlg->begin_active_widget_list == dlg->end_active_widget_list) {
1358
1359 if (dlg->scroll) {
1360 dlg->scroll->count = 0;
1361 }
1362
1363 if (dlg->begin_active_widget_list == dlg->begin_widget_list) {
1364 dlg->begin_widget_list = dlg->begin_widget_list->next;
1365 }
1366
1367 if (dlg->end_active_widget_list == dlg->end_widget_list) {
1368 dlg->end_widget_list = dlg->end_widget_list->prev;
1369 }
1370
1371 dlg->begin_active_widget_list = NULL;
1372 dlg->active_widget_list = NULL;
1373 dlg->end_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) {
1406 dlg->active_widget_list = dlg->active_widget_list->next;
1407 clear_wflag(dlg->active_widget_list, WF_HIDDEN);
1408
1409 /* Look for the widget in the non-visible part */
1410 buf = dlg->end_active_widget_list;
1411 while (buf != dlg->active_widget_list) {
1412 if (buf == pwidget) {
1413 widget_found = TRUE;
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 */
1434 widget_undraw(buf);
1435 widget_mark_dirty(buf);
1436 FREESURFACE(buf->gfx);
1437 goto std;
1438 }
1439 } else {
1440 clear_wflag(buf, WF_HIDDEN);
1441
1442 std: 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) {
1460 widget_undraw(dlg->scroll->pscroll_bar);
1461 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1462 refresh_widget_background(dlg->scroll->pscroll_bar);
1463 }
1464 }
1465
1466 } else {
1467 /* No scrollbar */
1468 buf = dlg->begin_active_widget_list;
1469
1470 /* Undraw last widget */
1471 widget_undraw(buf);
1472 widget_mark_dirty(buf);
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) {
1516 widget_undraw(dlg->scroll->pscroll_bar);
1517 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1518 refresh_widget_background(dlg->scroll->pscroll_bar);
1519 }
1520
1521 return TRUE;
1522}
1523
1524/**********************************************************************/
1527 void setup_vertical_scrollbar_default_callbacks(struct scroll_bar *scroll)
1528{
1529 fc_assert_ret(scroll != NULL);
1530
1531 if (scroll->up_left_button) {
1532 scroll->up_left_button->action = std_up_advanced_dlg_callback;
1533 }
1534 if (scroll->down_right_button) {
1535 scroll->down_right_button->action = std_down_advanced_dlg_callback;
1536 }
1537 if (scroll->pscroll_bar) {
1538 scroll->pscroll_bar->action = std_vscroll_advanced_dlg_callback;
1539 }
1540}
1541
1542/**************************************************************************
1543 Horizontal Scrollbar
1544**************************************************************************/
1545
1546
1547/**********************************************************************/
1550 Uint32 create_horizontal_scrollbar(struct advanced_dialog *dlg,
1551 Sint16 start_x, Sint16 start_y,
1552 Uint16 width, Uint16 active,
1553 bool create_scrollbar, bool create_buttons,
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
1568 buf = dlg->end_active_widget_list;
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;
1583 set_wstate(buf, FC_WS_NORMAL);
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;
1594 widget_add_as_prev(buf, dlg->begin_widget_list);
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;
1604 set_wstate(buf, FC_WS_NORMAL);
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;
1614 dlg->scroll->down_right_button = buf;
1615 widget_add_as_prev(buf, dlg->begin_widget_list);
1616 dlg->begin_widget_list = buf;
1617 }
1618
1619 if (create_scrollbar) {
1620 /* create vscrollbar */
1621 buf = create_horizontal(current_theme->horiz, pwindow->dst,
1622 width, WF_RESTORE_BACKGROUND);
1623
1624 buf->id = ID_SCROLLBAR;
1625 buf->data.ptr = (void *)dlg;
1626 set_wstate(buf, FC_WS_NORMAL);
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;
1648 widget_add_as_prev(buf, dlg->begin_widget_list);
1649 dlg->begin_widget_list = buf;
1650
1651 if (!count) {
1652 count = buf->size.h;
1653 }
1654 }
1655
1656 return count;
1657}
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
current_theme
QString current_theme
Definition fc_client.cpp:65
flush_dirty
void flush_dirty(void)
Definition mapview.c:450
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
FilterMouseMotionEvents
int FilterMouseMotionEvents(void *data, SDL_Event *event)
Definition gui_main.c:572
MOVE_STEP_Y
int MOVE_STEP_Y
Definition gui_main.c:101
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:593
MOVE_STEP_X
int MOVE_STEP_X
Definition gui_main.c:100
selected_widget
struct widget * selected_widget
Definition widget.c:48
adj_size
#define adj_size(size)
Definition gui_main.h:138
DEFAULT_MOVE_STEP
#define DEFAULT_MOVE_STEP
Definition gui_main.h:110
PRESSED_EVENT
#define PRESSED_EVENT(event)
Definition gui_main.h:68
colors.h
graphics.h
mapview.h
gui_id.h
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
gui_tilespec.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
UP_DOWN
Definition widget_scrollbar.c:39
UP_DOWN::end_widget_list
struct widget * end_widget_list
Definition widget_scrollbar.c:43
UP_DOWN::step
int step
Definition widget_scrollbar.c:46
UP_DOWN::old_y
float old_y
Definition widget_scrollbar.c:45
UP_DOWN::begin_widget_list
struct widget * begin_widget_list
Definition widget_scrollbar.c:42
UP_DOWN::offset
int offset
Definition widget_scrollbar.c:49
UP_DOWN::vscroll
struct scroll_bar * vscroll
Definition widget_scrollbar.c:44
UP_DOWN::begin
struct widget * begin
Definition widget_scrollbar.c:40
UP_DOWN::end
struct widget * end
Definition widget_scrollbar.c:41
UP_DOWN::prev_x
int prev_x
Definition widget_scrollbar.c:47
UP_DOWN::prev_y
int prev_y
Definition widget_scrollbar.c:48
advanced_dialog
Definition widget.h:180
advanced_dialog::active_widget_list
struct widget * active_widget_list
Definition widget.h:186
advanced_dialog::end_widget_list
struct widget * end_widget_list
Definition widget.h:182
advanced_dialog::begin_widget_list
struct widget * begin_widget_list
Definition widget.h:181
advanced_dialog::begin_active_widget_list
struct widget * begin_active_widget_list
Definition widget.h:184
advanced_dialog::end_active_widget_list
struct widget * end_active_widget_list
Definition widget.h:185
advanced_dialog::scroll
struct scroll_bar * scroll
Definition widget.h:187
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::up_left_button
struct widget * up_left_button
Definition widget_scrollbar.h:21
scroll_bar::pscroll_bar
struct widget * pscroll_bar
Definition widget_scrollbar.h:22
scroll_bar::active
Uint8 active
Definition widget_scrollbar.h:24
scroll_bar::max
Sint16 max
Definition widget_scrollbar.h:29
scroll_bar::step
Uint8 step
Definition widget_scrollbar.h:25
scroll_bar::count
Uint16 count
Definition widget_scrollbar.h:27
scroll_bar::min
Sint16 min
Definition widget_scrollbar.h:28
scroll_bar::down_right_button
struct widget * down_right_button
Definition widget_scrollbar.h:23
sdl2_data::event
SDL_Event event
Definition graphics.h:217
widget
Definition widget.h:112
widget::next
struct widget * next
Definition widget.h:113
widget::data
union widget::@214 data
widget::dst
struct gui_layer * dst
Definition widget.h:116
widget::gfx
SDL_Surface * gfx
Definition widget.h:120
widget::prev
struct widget * prev
Definition widget.h:114
widget::action
int(* action)(struct widget *)
Definition widget.h:157
widget::cont
struct container * cont
Definition widget.h:127
widget::private_data
union widget::@215 private_data
widget::adv_dlg
struct advanced_dialog * adv_dlg
Definition widget.h:139
widget::theme
SDL_Surface * theme
Definition widget.h:118
widget::size
SDL_Rect size
Definition widget.h:145
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
themespec.h
refresh_widget_background
void refresh_widget_background(struct widget *pwidget)
Definition widget.c:1150
unselect_widget_action
void unselect_widget_action(void)
Definition widget.c:417
widget_add_as_prev
void widget_add_as_prev(struct widget *new_widget, struct widget *add_dock)
Definition widget.c:601
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:719
widget.h
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
widget_p.h
std_vscroll_advanced_dlg_callback
static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
Definition widget_scrollbar.c:464
std_down_advanced_dlg_callback
static int std_down_advanced_dlg_callback(struct widget *pwidget)
Definition widget_scrollbar.c:437
redraw_horiz
static int redraw_horiz(struct widget *horiz)
Definition widget_scrollbar.c:269
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:638
scroll_mouse_button_up
static Uint16 scroll_mouse_button_up(SDL_MouseButtonEvent *button_event, void *data)
Definition widget_scrollbar.c:1050
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:1349
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:1550
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:1059
create_horizontal
struct widget * create_horizontal(SDL_Surface *horiz_theme, struct gui_layer *pdest, Uint16 width, Uint32 flags)
Definition widget_scrollbar.c:301
create_horizontal_surface
static SDL_Surface * create_horizontal_surface(SDL_Surface *horiz_theme, Uint8 state, Uint16 width)
Definition widget_scrollbar.c:212
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:1088
scroll_mouse_motion_handler
static Uint16 scroll_mouse_motion_handler(SDL_MouseMotionEvent *motion_event, void *data)
Definition widget_scrollbar.c:962
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:1110
draw_horiz
int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
Definition widget_scrollbar.c:325
setup_vertical_scrollbar_default_callbacks
void setup_vertical_scrollbar_default_callbacks(struct scroll_bar *scroll)
Definition widget_scrollbar.c:1527
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:920
get_position
static int get_position(struct advanced_dialog *dlg)
Definition widget_scrollbar.c:357
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:572
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:1151
inside_scroll_down_loop
static void inside_scroll_down_loop(void *data)
Definition widget_scrollbar.c:873
get_step
static int get_step(struct scroll_bar *scroll)
Definition widget_scrollbar.c:341
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:491
std_up_advanced_dlg_callback
static int std_up_advanced_dlg_callback(struct widget *pwidget)
Definition widget_scrollbar.c:410
create_vertical_surface
static SDL_Surface * create_vertical_surface(SDL_Surface *vert_theme, enum widget_state state, Uint16 height)
Definition widget_scrollbar.c:74
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