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