Freeciv-3.2
Loading...
Searching...
No Matches
helpdlg.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 "fcintl.h"
27#include "log.h"
28
29/* common */
30#include "game.h"
31#include "government.h"
32#include "movement.h"
33
34/* client */
35#include "client_main.h"
36#include "helpdata.h"
37
38/* gui-sdl2 */
39#include "colors.h"
40#include "graphics.h"
41#include "gui_id.h"
42#include "gui_main.h"
43#include "gui_tilespec.h"
44#include "mapview.h"
45#include "repodlgs.h"
46#include "sprite.h"
47#include "themespec.h"
48#include "widget.h"
49
50#include "helpdlg.h"
51
52static struct advanced_dialog *help_dlg = NULL;
53
55 struct widget *targets[6], *sub_targets[6];
57 struct widget *dock;
60};
61
67
69
70static const int bufsz = 8192;
71
72static int change_tech_callback(struct widget *pwidget);
73
74/**********************************************************************/
81
82/**********************************************************************/
93
94/**********************************************************************/
101{
102 log_debug("popup_help_dialog_typed : PORT ME");
103}
104
105/**********************************************************************/
118
119/**********************************************************************/
122static int help_dlg_window_callback(struct widget *pwindow)
123{
124 return -1;
125}
126
127/**********************************************************************/
130static int exit_help_dlg_callback(struct widget *pwidget)
131{
134 flush_dirty();
135 }
136
137 return -1;
138}
139
140/**********************************************************************/
143static int change_gov_callback(struct widget *pwidget)
144{
146 popup_gov_info(MAX_ID - pwidget->id);
147 }
148
149 return -1;
150}
151
152/**********************************************************************/
155void popup_gov_info(int gov)
156{
157}
158
159/**********************************************************************/
162static int change_impr_callback(struct widget *pwidget)
163{
165 popup_impr_info(MAX_ID - pwidget->id);
166 }
167
168 return -1;
169}
170
171/**********************************************************************/
174static void redraw_impr_info_dlg(void)
175{
176 SDL_Color bg_color = {255, 255, 255, 64};
177 struct widget *pwindow = help_dlg->end_widget_list;
178 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
179 SDL_Rect dst;
180
181 redraw_group(pwindow->prev, pwindow, FALSE);
182
183 dst.x = store->dock->prev->size.x - adj_size(10);
184 dst.y = store->dock->prev->size.y - adj_size(10);
185 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
186 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
187
188 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
189
190 create_frame(pwindow->dst->surface,
191 dst.x, dst.y, dst.w, dst.h,
193
194 /*------------------------------------- */
196 widget_flush(pwindow);
197}
198
199/**********************************************************************/
203{
204 SDL_Color bg_color = {255, 255, 255, 128};
205 struct widget *pwindow;
206 struct units_buttons *store;
207 struct widget *close_button = NULL;
210 struct widget *impr_name_label = NULL;
211 struct widget *cost_label = NULL;
212 struct widget *upkeep_label = NULL;
213 struct widget *requirement_label = NULL;
215 struct widget *obsolete_by_label = NULL;
217 struct widget *help_text_label = NULL;
218 struct widget *dock;
220 utf8_str *pstr;
221 SDL_Surface *surf;
222 int h, start_x, start_y, impr_type_count;
223 bool created, text = FALSE;
224 int scrollbar_width = 0;
225 struct impr_type *pimpr_type;
226 char buffer[64000];
227 SDL_Rect area;
228 struct advance *obsTech = NULL;
229
232 }
233
234 if (!help_dlg) {
235 SDL_Surface *background_tmpl, *background, *impr_name, *icon;
236 SDL_Rect dst;
237
239 created = TRUE;
240
241 /* Create dialog */
242 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
243 store = fc_calloc(1, sizeof(struct units_buttons));
244
245 /* Create window */
246 title = create_utf8_from_char_fonto(_("Help : Improvements"),
248 title->style |= TTF_STYLE_BOLD;
249
252 set_wstate(pwindow , FC_WS_NORMAL);
253 pwindow->data.ptr = (void *)store;
254 add_to_gui_list(ID_WINDOW, pwindow);
255
256 help_dlg->end_widget_list = pwindow;
257
258 area = pwindow->area;
259 /* ------------------ */
260
261 /* Close button */
262 close_button = create_themeicon(current_theme->small_cancel_icon,
263 pwindow->dst,
266 close_button->info_label
267 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"),
269 close_button->action = exit_help_dlg_callback;
270 set_wstate(close_button, FC_WS_NORMAL);
271 close_button->key = SDLK_ESCAPE;
272
273 add_to_gui_list(ID_BUTTON, close_button);
274
275 /* ------------------ */
276 dock = close_button;
277
279 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
280
281 /* Background template for entries in scroll list */
284
286 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
288
289 impr_type_count = 0;
290 improvement_iterate(pimprove) {
291
292 /* Copy background surface */
293 background = copy_surface(background_tmpl);
294
295 /* Blit improvement name */
298 dst.x = adj_size(40) + (background->w - impr_name->w - adj_size(40)) / 2;
299 dst.y = (background->h - impr_name->h) / 2;
300 alphablit(impr_name, NULL, background, &dst, 255);
302
303 /* Blit improvement icon */
305 adj_size(36), adj_size(36), 1, TRUE, TRUE);
306 dst.x = adj_size(5);
307 dst.y = (background->h - icon->h) / 2;
308 alphablit(icon, NULL, background, &dst, 255);
309 FREESURFACE(icon);
310
311 improvement_button = create_icon2(background, pwindow->dst,
313
317
318 if (impr_type_count++ >= 10) {
320 }
321
323
325
329
330 if (impr_type_count > 10) {
333 }
334
335 /* Toggle techs list button */
337 current_theme->up_icon,
338 pwindow->dst,
339 _("Improvements"),
340 FONTO_DEFAULT, 0);
341#if 0
343 if (store->show_tree) {
345 }
346#endif
347
350
352
353 dock = list_toggle_button;
354 store->dock = dock;
355 } else {
356 created = FALSE;
358 pwindow = help_dlg->end_widget_list;
359 store = (struct units_buttons *)pwindow->data.ptr;
360 dock = store->dock;
361
362 area = pwindow->area;
363
364 /* Delete any previous list entries */
367 dock->prev);
369 }
370 }
371
373
377 adj_size(48), 1, TRUE, TRUE),
378 pwindow->dst,
381
385
387 sprintf(buffer, "%s %d", _("Base Cost:"),
390 buffer,
391 FONTO_ATTENTION, 0);
392 cost_label->id = ID_LABEL;
395
396 if (!is_wonder(pimpr_type)) {
397 sprintf(buffer, "%s %d", _("Upkeep:"), pimpr_type->upkeep);
399 buffer,
400 FONTO_ATTENTION, 0);
404 }
405 }
406
407 /* Requirement */
409 _("Requirement:"),
410 FONTO_ATTENTION, 0);
414
415 /* FIXME: this should show ranges, negated reqs, and all the
416 * MAX_NUM_REQS reqs.
417 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
418 * definition. */
420 if (!preq->present) {
421 continue;
422 }
425 universal_name_translation(&preq->source, buffer, sizeof(buffer)),
428 if (preq->source.kind != VUT_ADVANCE) {
429 break; /* FIXME */
430 }
431 requirement_label2->id = MAX_ID - advance_number(preq->source.value.advance);
432 requirement_label2->string_utf8->fgcol
433 = *get_tech_color(advance_number(preq->source.value.advance));
436 break;
438
439 if (requirement_label2 == NULL) {
441 Q_("?req:None"),
442 FONTO_ATTENTION, 0);
444 }
445
449
450 /* Obsolete by */
452 _("Obsolete by:"),
453 FONTO_ATTENTION, 0);
457
459 if (pobs->source.kind == VUT_ADVANCE) {
460 obsTech = pobs->source.value.advance;
461 break;
462 }
464
465 if (obsTech == NULL) {
467 _("Never"),
468 FONTO_ATTENTION, 0);
470 } else {
477 obsolete_by_label2->string_utf8->fgcol
481 }
485
486 /* Helptext */
487 start_x = (area.x + 1 + scrollbar_width + help_dlg->end_active_widget_list->size.w + adj_size(20));
488
489 buffer[0] = '\0';
490 helptext_building(buffer, sizeof(buffer), client.conn.playing, NULL,
491 pimpr_type);
492 if (buffer[0] != '\0') {
494
499 text = TRUE;
500 }
501
503
504 /* --------------------------------------------------------- */
505 if (created) {
507 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
508 FREESURFACE(surf);
509 }
510
511 area = pwindow->area;
512
513 widget_set_position(pwindow,
514 (main_window_width() - pwindow->size.w) / 2,
515 (main_window_height() - pwindow->size.h) / 2);
516
517 /* Exit button */
518 close_button = pwindow->prev;
519 widget_set_position(close_button,
520 area.x + area.w - close_button->size.w - 1,
521 pwindow->size.y + adj_size(2));
522
523 /* List toggle button */
524 list_toggle_button = store->dock;
526
527 /* List entries */
529 area.y + list_toggle_button->size.h, 0, 0,
532
533 /* Scrollbar */
534 if (help_dlg->scroll) {
536 area.x, area.y + list_toggle_button->size.h,
537 h, FALSE);
538 }
539 }
540
541 impr_name_label = store->dock->prev;
542 widget_set_position(impr_name_label, start_x, area.y + adj_size(16));
543
544 start_y = impr_name_label->size.y + impr_name_label->size.h + adj_size(10);
545
549 if (!is_wonder(pimpr_type)) {
550 upkeep_label = cost_label->prev;
552 cost_label->size.x + cost_label->size.w + adj_size(20),
553 start_y);
554 }
555 start_y += cost_label->size.h;
556 }
557
560
563 requirement_label->size.x + requirement_label->size.w + adj_size(5),
564 start_y);
565
566 if (store->obsolete_by_button) {
569 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
570 start_y);
571
574 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
575 start_y);
576
577 start_y += obsolete_by_label2->size.h;
578 }
579
580 start_y += adj_size(30);
581
582 if (text) {
584 }
585
587}
588
589/**********************************************************************/
592static int change_unit_callback(struct widget *pwidget)
593{
595 popup_unit_info(MAX_ID - pwidget->id);
596 }
597
598 return -1;
599}
600
601/**********************************************************************/
604static void redraw_unit_info_dlg(void)
605{
606 SDL_Color bg_color = {255, 255, 255, 64};
607 struct widget *pwindow = help_dlg->end_widget_list;
608 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
609 SDL_Rect dst;
610
611 redraw_group(pwindow->prev, pwindow, FALSE);
612
613 dst.x = store->dock->prev->size.x - adj_size(10);
614 dst.y = store->dock->prev->size.y - adj_size(10);
615 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
616 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
617
618 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
619
620 create_frame(pwindow->dst->surface,
621 dst.x, dst.y, dst.w, dst.h,
623
624 /*------------------------------------- */
626 widget_flush(pwindow);
627}
628
629/**********************************************************************/
633{
634 SDL_Color bg_color = {255, 255, 255, 128};
635 struct widget *pwindow;
636 struct units_buttons *store;
637 struct widget *close_button = NULL;
639 struct widget *unit_button = NULL;
640 struct widget *unit_name_label = NULL;
641 struct widget *unit_info_label = NULL;
642 struct widget *requirement_label = NULL;
644 struct widget *obsolete_by_label = NULL;
646 struct widget *help_text_label = NULL;
647 struct widget *dock;
649 utf8_str *pstr;
650 SDL_Surface *surf;
651 int h, start_x, start_y, utype_count;
652 bool created, text = FALSE;
653 int scrollbar_width = 0;
654 struct unit_type *punittype;
655 char buffer[bufsz];
656 SDL_Rect area;
657 struct advance *req;
658
661 }
662
663 /* Create new dialog if it doesn't exist yet */
664 if (!help_dlg) {
665 SDL_Surface *background_tmpl, *background, *unit_name, *icon;
666 SDL_Rect dst;
667
669 created = TRUE;
670
671 /* Create dialog */
672 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
673 store = fc_calloc(1, sizeof(struct units_buttons));
674
675 /* Create window */
677 title->style |= TTF_STYLE_BOLD;
678
681 set_wstate(pwindow , FC_WS_NORMAL);
682 pwindow->data.ptr = (void *)store;
683 add_to_gui_list(ID_WINDOW, pwindow);
684
685 help_dlg->end_widget_list = pwindow;
686
687 area = pwindow->area;
688
689 /* ------------------ */
690
691 /* Close button */
692 close_button = create_themeicon(current_theme->small_cancel_icon,
693 pwindow->dst,
696 close_button->info_label
697 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
698 close_button->action = exit_help_dlg_callback;
699 set_wstate(close_button, FC_WS_NORMAL);
700 close_button->key = SDLK_ESCAPE;
701
702 add_to_gui_list(ID_BUTTON, close_button);
703
704 /* ------------------ */
705 dock = close_button;
706
707 /* --- Create scrollable unit list on the left side ---*/
708
710 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
711
712 /* Background template for entries in scroll list */
715
717 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
719
720 utype_count = 0;
722
723 /* Copy background surface */
724 background = copy_surface(background_tmpl);
725
726 /* Blit unit name */
729 dst.x = adj_size(35) + (background->w - unit_name->w - adj_size(35)) / 2;
730 dst.y = (background->h - unit_name->h) / 2;
731 alphablit(unit_name, NULL, background, &dst, 255);
733
734 /* Blit unit icon */
736 adj_size(36), adj_size(36), 1, TRUE, TRUE);
737 dst.x = (adj_size(35) - icon->w) / 2;
738 dst.y = (background->h - icon->h) / 2;
739 alphablit(icon, NULL, background, &dst, 255);
740 FREESURFACE(icon);
741
742 unit_button = create_icon2(background, pwindow->dst,
744
748
749 if (utype_count++ >= 10) {
751 }
752
754
756
760
761 if (utype_count > 10) {
764 }
765
766 /* Toggle techs list button */
768 current_theme->up_icon,
769 pwindow->dst,
770 _("Units"),
771 FONTO_DEFAULT, 0);
772#if 0
774 if (store->show_tree) {
776 }
777#endif
778
781
783
784 dock = list_toggle_button;
785 store->dock = dock;
786 } else {
787 created = FALSE;
789 pwindow = help_dlg->end_widget_list;
790 store = (struct units_buttons *)pwindow->data.ptr;
791 dock = store->dock;
792
793 area = pwindow->area;
794
795 /* Delete any previous list entries */
798 dock->prev);
800 }
801 }
802
809
813
814 {
815 char buf[2048];
816
817 fc_snprintf(buf, sizeof(buf), "%s %d %s",
819 PL_("shield", "shields", utype_build_shield_cost_base(punittype)));
820
821 if (punittype->pop_cost) {
822 cat_snprintf(buf, sizeof(buf), " %d %s",
823 punittype->pop_cost, PL_("citizen", "citizens",
824 punittype->pop_cost));
825 }
826
827 cat_snprintf(buf, sizeof(buf), " %s", _("Upkeep:"));
828
829 if (punittype->upkeep[O_SHIELD]) {
830 cat_snprintf(buf, sizeof(buf), " %d %s",
831 punittype->upkeep[O_SHIELD], PL_("shield", "shields",
832 punittype->upkeep[O_SHIELD]));
833 }
834 if (punittype->upkeep[O_FOOD]) {
835 cat_snprintf(buf, sizeof(buf), " %d %s",
836 punittype->upkeep[O_FOOD], PL_("food", "foods",
837 punittype->upkeep[O_FOOD]));
838 }
839 if (punittype->upkeep[O_GOLD]) {
840 cat_snprintf(buf, sizeof(buf), " %d %s",
841 punittype->upkeep[O_GOLD], PL_("gold", "golds",
842 punittype->upkeep[O_GOLD]));
843 }
844 if (punittype->happy_cost) {
845 cat_snprintf(buf, sizeof(buf), " %d %s",
846 punittype->happy_cost, PL_("citizen", "citizens",
847 punittype->happy_cost));
848 }
849
850 cat_snprintf(buf, sizeof(buf), "\n%s %d %s %d %s %s\n%s %d %s %d %s %d",
851 _("Attack:"), punittype->attack_strength,
852 _("Defense:"), punittype->defense_strength,
853 _("Move:"), move_points_text(punittype->move_rate, TRUE),
854 _("Vision:"), punittype->vision_radius_sq,
855 _("Firepower:"), punittype->firepower,
856 _("Hitpoints:"), punittype->hp);
857
859 FONTO_ATTENTION, 0);
863 }
864
865 /* Requirement */
867 _("Requirement:"),
868 FONTO_ATTENTION, 0);
872
874
875 if (advance_number(req) == A_NONE) {
877 Q_("?tech:None"),
878 FONTO_ATTENTION, 0);
880 } else {
882
889 requirement_label2->string_utf8->fgcol = *get_tech_color(req_id);
892 }
896
897 /* Obsolete by */
899 _("Obsolete by:"),
900 FONTO_ATTENTION, 0);
904
905 if (punittype->obsoleted_by == U_NOT_OBSOLETED) {
907 Q_("?utype:None"),
908 FONTO_ATTENTION, 0);
910 } else {
911 const struct unit_type *utype = punittype->obsoleted_by;
912 struct advance *obs_req = utype_primary_tech_req(utype);
913
919 obsolete_by_label2->string_utf8->fgcol
924 }
926 dock = obsolete_by_label2;
928
929 /* Helptext */
930 start_x = (area.x + 1 + scrollbar_width + help_dlg->active_widget_list->size.w + adj_size(20));
931
932 buffer[0] = '\0';
933 helptext_unit(buffer, sizeof(buffer), client.conn.playing, "", utype_by_number(type_id));
934 if (buffer[0] != '\0') {
936
941 text = TRUE;
942 }
943
945
946 /* --------------------------------------------------------- */
947 if (created) {
948
950 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
951 FREESURFACE(surf);
952 }
953
954 area = pwindow->area;
955
956 widget_set_position(pwindow,
957 (main_window_width() - pwindow->size.w) / 2,
958 (main_window_height() - pwindow->size.h) / 2);
959
960 /* Exit button */
961 close_button = pwindow->prev;
962 widget_set_position(close_button,
963 area.x + area.w - close_button->size.w - 1,
964 pwindow->size.y + adj_size(2));
965
966 /* List toggle button */
967 list_toggle_button = store->dock;
969
970 /* List entries */
972 area.y + list_toggle_button->size.h, 0, 0,
975
976 /* Scrollbar */
977 if (help_dlg->scroll) {
979 area.x, area.y + list_toggle_button->size.h,
980 h, FALSE);
981 }
982 }
983
984 unit_name_label = store->dock->prev;
985 widget_set_position(unit_name_label, start_x, area.y + adj_size(16));
986
987 start_y = unit_name_label->size.y + unit_name_label->size.h + adj_size(10);
988
991
992 start_y += unit_info_label->size.h;
993
996
999 requirement_label->size.x + requirement_label->size.w + adj_size(5),
1000 start_y);
1001
1004 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
1005 start_y);
1006
1009 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
1010 start_y);
1011
1012 start_y += obsolete_by_label2->size.h + adj_size(20);
1013
1014 if (text) {
1017 }
1018
1020}
1021
1022/* =============================================== */
1023/* ==================== Tech Tree ================ */
1024/* =============================================== */
1025
1026/**********************************************************************/
1029static int change_tech_callback(struct widget *pwidget)
1030{
1032 popup_tech_info(MAX_ID - pwidget->id);
1033 }
1034
1035 return -1;
1036}
1037
1038/**********************************************************************/
1041static int show_tech_tree_callback(struct widget *pwidget)
1042{
1044 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1045
1046 store->show_tree = !store->show_tree;
1047 if (!store->show_tree) {
1048 store->show_full_tree = FALSE;
1049 store->dock->theme2 = current_theme->up_icon;
1050 }
1051 popup_tech_info(MAX_ID - store->dock->prev->id);
1052 }
1053
1054 return -1;
1055}
1056
1057/**********************************************************************/
1060static void redraw_tech_info_dlg(void)
1061{
1062 SDL_Color bg_color = {255, 255, 255, 64};
1063 struct widget *pwindow = help_dlg->end_widget_list;
1064 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1066 utf8_str *pstr;
1067 SDL_Rect dst;
1068
1069 redraw_group(pwindow->prev, pwindow, FALSE);
1070
1071 dst.x = store->dock->prev->prev->size.x - adj_size(10);
1072 dst.y = store->dock->prev->prev->size.y - adj_size(10);
1073 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
1074 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
1075
1076 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1077
1078 create_frame(pwindow->dst->surface,
1079 dst.x, dst.y, dst.w, dst.h,
1081
1082 /* -------------------------- */
1084 pstr->style |= TTF_STYLE_BOLD;
1085
1087 dst.x = store->dock->prev->prev->size.x;
1088 if (store->targets[0]) {
1089 dst.y = store->targets[0]->size.y - text0->h;
1090 } else {
1091 dst.y = store->dock->prev->prev->size.y
1092 + store->dock->prev->prev->size.h + adj_size(10);
1093 }
1094
1095 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1097
1098 if (store->sub_targets[0]) {
1099 int i;
1100
1102
1103 copy_chars_to_utf8_str(pstr, _("( with "));
1105
1108 i = 0;
1110 dst.x = store->sub_targets[i]->size.x - text0->w;
1111 dst.y = store->sub_targets[i]->size.y;
1112
1113 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1114 dst.x = store->sub_targets[i]->size.x + store->sub_targets[i]->size.w;
1115 dst.y = store->sub_targets[i]->size.y;
1116
1117 alphablit(text1, NULL, pwindow->dst->surface, &dst, 255);
1118 i++;
1119 }
1120
1123 }
1125
1127 widget_flush(pwindow);
1128}
1129
1130/**********************************************************************/
1134 struct widget *pwindow,
1135 struct techs_buttons *store)
1136{
1137 struct widget *pwidget;
1138 struct widget *last, *budynki;
1139 struct widget *dock = store->dock;
1141 int start_x, start_y, imp_count, unit_count, flags_count, gov_count;
1142 char buffer[bufsz];
1143 SDL_Surface *surf;
1144
1145 start_x = (pwindow->area.x + adj_size(1) + width + help_dlg->active_widget_list->size.w + adj_size(20));
1146
1147 /* Tech tree icon */
1148 pwidget = create_icon2(current_theme->tech_tree_icon, pwindow->dst,
1150
1151 set_wstate(pwidget, FC_WS_NORMAL);
1153 pwidget->id = MAX_ID - tech;
1154 widget_add_as_prev(pwidget, dock);
1155 dock = pwidget;
1156
1157 /* Tech name (heading) */
1158 pwidget
1160 pwindow->dst,
1163
1164 pwidget->id = ID_LABEL;
1165 widget_add_as_prev(pwidget, dock);
1166 dock = pwidget;
1167
1168 /* Target techs */
1169 targets_count = 0;
1171 if ((targets_count < 6)
1172 && (advance_required(aidx, AR_ONE) == tech
1173 || advance_required(aidx, AR_TWO) == tech)) {
1174 pwidget
1179 pwidget->string_utf8->fgcol = *get_tech_color(aidx);
1180 max_width = MAX(max_width, pwidget->size.w);
1181 set_wstate(pwidget, FC_WS_NORMAL);
1182 pwidget->action = change_tech_callback;
1183 pwidget->id = MAX_ID - aidx;
1184 widget_add_as_prev(pwidget, dock);
1185 dock = pwidget;
1186 store->targets[targets_count++] = pwidget;
1187 }
1189 if (targets_count < 6) {
1190 store->targets[targets_count] = NULL;
1191 }
1192
1194 if (targets_count > 0) {
1195 int sub_tech;
1196
1197 for (i = 0; i < targets_count; i++) {
1198 sub_tech = MAX_ID - store->targets[i]->id;
1199 if (advance_required(sub_tech, AR_ONE) == tech
1202 } else if (advance_required(sub_tech, AR_TWO) == tech
1205 } else {
1206 continue;
1207 }
1208 pwidget
1214 set_wstate(pwidget, FC_WS_NORMAL);
1215 pwidget->action = change_tech_callback;
1216 pwidget->id = MAX_ID - sub_tech;
1217 widget_add_as_prev(pwidget, dock);
1218 dock = pwidget;
1219 store->sub_targets[sub_targets_count++] = pwidget;
1220 }
1221 }
1222 if (sub_targets_count < 6) {
1224 }
1225
1226 /* Fill array with iprvm. icons */
1227 budynki = pwidget;
1228
1229 /* Target governments */
1230 gov_count = 0;
1231 governments_iterate(gov) {
1232 requirement_vector_iterate(&(gov->reqs), preq) {
1233 if (VUT_ADVANCE == preq->source.kind
1234 && advance_number(preq->source.value.advance) == tech) {
1235
1236 pwidget
1238 pwindow->dst,
1242 set_wstate(pwidget, FC_WS_NORMAL);
1243 pwidget->action = change_gov_callback;
1244 pwidget->id = MAX_ID - government_index(gov);
1245 widget_add_as_prev(pwidget, dock);
1246 dock = pwidget;
1247 gov_count++;
1248 }
1251
1252 /* Target improvements */
1253 imp_count = 0;
1254 improvement_iterate(pimprove) {
1255 if (valid_improvement(pimprove)) {
1256 /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs.
1257 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
1258 * definition. */
1259 requirement_vector_iterate(&(pimprove->reqs), preq) {
1260 if (VUT_ADVANCE == preq->source.kind
1261 && advance_number(preq->source.value.advance) == tech) {
1262 surf = get_building_surface(pimprove);
1264 resize_surface_box(surf, adj_size(48), adj_size(48), 1, TRUE,
1265 TRUE),
1266 pwindow->dst,
1270 set_wstate(pwidget, FC_WS_NORMAL);
1271 if (is_wonder(pimprove)) {
1273 }
1274 pwidget->action = change_impr_callback;
1275 pwidget->id = MAX_ID - improvement_number(pimprove);
1276 widget_add_as_prev(pwidget, dock);
1277 dock = pwidget;
1278 imp_count++;
1279 }
1280
1281 break;
1283 }
1285
1286 unit_count = 0;
1291 adj_size(48), adj_size(48), 1, TRUE, TRUE),
1294 set_wstate(pwidget, FC_WS_NORMAL);
1295 pwidget->action = change_unit_callback;
1296 pwidget->id = MAX_ID - utype_number(un);
1297 widget_add_as_prev(pwidget, dock);
1298 dock = pwidget;
1299 unit_count++;
1300 }
1302
1303 buffer[0] = '\0';
1304 if (tech != A_NONE) {
1305 helptext_advance(buffer, sizeof(buffer), client.conn.playing, "", tech);
1306 }
1307 if (buffer[0] != '\0') {
1309
1311 pwidget = create_iconlabel(NULL, pwindow->dst, pstr, 0);
1312 pwidget->id = ID_LABEL;
1313 widget_add_as_prev(pwidget, dock);
1314 flags_count = 1;
1315 } else {
1316 flags_count = 0;
1317 }
1318
1319 last = pwidget;
1320 /* --------------------------------------------- */
1321
1322 /* Tree button */
1323 pwidget = store->dock->prev;
1324 pwidget->size.x = pwindow->area.x + pwindow->area.w - pwidget->size.w - adj_size(17);
1325 pwidget->size.y = pwindow->area.y + adj_size(16);
1326
1327 /* Tech label */
1328 pwidget = pwidget->prev;
1329 pwidget->size.x = start_x;
1330 pwidget->size.y = pwindow->area.y + adj_size(16);
1331 start_y = pwidget->size.y + pwidget->size.h + adj_size(30);
1332
1333 if (targets_count) {
1334 int j = 0;
1335
1336 i = 0;
1337
1338 while (i < 6 && store->targets[i]) {
1339 store->targets[i]->size.x = pwindow->size.x + start_x;
1340 store->targets[i]->size.y = start_y;
1341
1342 if (store->sub_targets[j]) {
1343 int t0 = MAX_ID - store->targets[i]->id;
1344 int t1 = MAX_ID - store->sub_targets[j]->id;
1345
1346 if (advance_required(t0, AR_ONE) == t1
1347 || advance_required(t0, AR_TWO) == t1) {
1348 store->sub_targets[j]->size.x = pwindow->size.x + start_x + max_width + 60;
1349 store->sub_targets[j]->size.y = store->targets[i]->size.y;
1350 j++;
1351 }
1352 }
1353
1354 start_y += store->targets[i]->size.h;
1355 i++;
1356 }
1357
1358 start_y += adj_size(10);
1359 }
1360 pwidget = NULL;
1361
1362 if (gov_count) {
1363 pwidget = budynki->prev;
1364 while (gov_count-- && pwidget) {
1365 pwidget->size.x = pwindow->size.x + start_x;
1366 pwidget->size.y = start_y;
1367 start_y += pwidget->size.h + adj_size(2);
1368 pwidget = pwidget->prev;
1369 }
1370 }
1371
1372 if (imp_count) {
1373 if (!pwidget) {
1374 pwidget = budynki->prev;
1375 }
1376 while (imp_count-- && pwidget) {
1377 pwidget->size.x = pwindow->size.x + start_x;
1378 pwidget->size.y = start_y;
1379 start_y += pwidget->size.h + adj_size(2);
1380 pwidget = pwidget->prev;
1381 }
1382 }
1383
1384 if (unit_count) {
1385 if (!pwidget) {
1386 pwidget = budynki->prev;
1387 }
1388 while (unit_count-- && pwidget) {
1389 pwidget->size.x = pwindow->size.x + start_x;
1390 pwidget->size.y = start_y;
1391 start_y += pwidget->size.h + adj_size(2);
1392 pwidget = pwidget->prev;
1393 }
1394 }
1395
1396 if (flags_count) {
1397 if (!pwidget) {
1398 pwidget = budynki->prev;
1399 }
1400 while (flags_count-- && pwidget) {
1401 pwidget->size.x = pwindow->size.x + start_x;
1402 pwidget->size.y = start_y;
1403 start_y += pwidget->size.h + adj_size(2);
1404 pwidget = pwidget->prev;
1405 }
1406 }
1407
1408 return last;
1409}
1410
1411/**********************************************************************/
1414static void redraw_tech_tree_dlg(void)
1415{
1417 SDL_Color bg_color = {255, 255, 255, 64};
1418 struct widget *pwindow = help_dlg->end_widget_list;
1419 struct widget *sub0, *sub1;
1420 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1421 struct widget *ptech = store->dock->prev;
1422 int i,j, tech, count;
1423 int step;
1424 int mod;
1425 SDL_Rect dst;
1426
1427 /* Redraw Window with exit button */
1428 redraw_group(pwindow->prev, pwindow, FALSE);
1429
1430 dst.x = pwindow->area.x + pwindow->area.w - adj_size(459) - adj_size(7);
1431 dst.y = pwindow->area.y + adj_size(6);
1432 dst.w = pwindow->area.w - (dst.x - pwindow->area.x) - adj_size(10);
1433 dst.h = pwindow->area.h - (dst.y - pwindow->area.y) - adj_size(10);
1434
1435 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1436
1437 create_frame(pwindow->dst->surface,
1438 dst.x, dst.y, dst.w, dst.h,
1440
1441 /* Draw req arrows */
1442 i = 0;
1443 while (i < 4 && store->sub_req[i]) {
1444 i++;
1445 }
1446 count = i;
1447
1448 i = 0;
1449 while (i < 2 && store->requirement_button[i]) {
1450 tech = MAX_ID - store->requirement_button[i]->id;
1451
1452 /* Find sub req's */
1453 if (i) {
1454 sub0 = NULL;
1455 for (j = count - 1; j >= 0; j--) {
1456 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1457 sub0 = store->sub_req[j];
1458 break;
1459 }
1460 }
1461
1462 sub1 = NULL;
1463 for (j = count - 1; j >= 0; j--) {
1464 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1465 sub1 = store->sub_req[j];
1466 break;
1467 }
1468 }
1469 } else {
1470 sub0 = NULL;
1471 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1472 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1473 sub0 = store->sub_req[j];
1474 break;
1475 }
1476 }
1477
1478 sub1 = NULL;
1479 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1480 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1481 sub1 = store->sub_req[j];
1482 break;
1483 }
1484 }
1485 }
1486
1487 /* Draw main Arrow */
1489 store->requirement_button[i]->size.x + store->requirement_button[i]->size.w,
1490 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1491 ptech->size.x,
1492 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1493 line_color);
1494
1495 /* Draw sub req arrows */
1496 if (sub0 || sub1) {
1498 store->requirement_button[i]->size.x - adj_size(10),
1499 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1500 store->requirement_button[i]->size.x ,
1501 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1502 line_color);
1503 }
1504
1505 if (sub0) {
1507 store->requirement_button[i]->size.x - adj_size(10),
1508 sub0->size.y + sub0->size.h / 2,
1509 store->requirement_button[i]->size.x - adj_size(10),
1510 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1511 line_color);
1513 sub0->size.x + sub0->size.w,
1514 sub0->size.y + sub0->size.h / 2,
1515 store->requirement_button[i]->size.x - adj_size(10),
1516 sub0->size.y + sub0->size.h / 2,
1517 line_color);
1518 }
1519
1520 if (sub1) {
1522 store->requirement_button[i]->size.x - adj_size(10),
1523 sub1->size.y + sub1->size.h / 2,
1524 store->requirement_button[i]->size.x - adj_size(10),
1525 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1526 line_color);
1528 sub1->size.x + sub1->size.w,
1529 sub1->size.y + sub1->size.h / 2,
1530 store->requirement_button[i]->size.x - adj_size(10),
1531 sub1->size.y + sub1->size.h / 2,
1532 line_color);
1533 }
1534 i++;
1535 }
1536
1537 i = 0;
1538 while (i < 6 && store->targets[i]) {
1539 i++;
1540 }
1541 count = i;
1542
1543 if (count > 4) {
1544 mod = 3;
1545 } else {
1546 mod = 2;
1547 }
1548
1549 for (i = 0; i < count; i++) {
1550 tech = MAX_ID - store->targets[i]->id;
1551 step = ptech->size.h / (count + 1);
1552
1553 switch ((i % mod)) {
1554 case 2:
1556 break;
1557 case 1:
1559 break;
1560 default:
1562 break;
1563 }
1564
1565 /* Find sub reqs */
1566 if (advance_required(tech, AR_ONE) == MAX_ID - ptech->id) {
1567 sub0 = ptech;
1568 } else {
1569 sub0 = NULL;
1570 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1571 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_ONE)) {
1572 sub0 = store->sub_targets[j];
1573 break;
1574 }
1575 }
1576 }
1577
1578 if (advance_required(tech, AR_TWO) == MAX_ID - ptech->id) {
1579 sub1 = ptech;
1580 } else {
1581 sub1 = NULL;
1582 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1583 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_TWO)) {
1584 sub1 = store->sub_targets[j];
1585 break;
1586 }
1587 }
1588 }
1589
1590 /* Draw sub targets arrows */
1591 if (sub0 || sub1) {
1592 create_line(store->targets[i]->dst->surface,
1593 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1594 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1595 store->targets[i]->size.x ,
1596 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1597 line_color);
1598 }
1599
1600 if (sub0) {
1601 int y;
1602
1603 if (sub0 == ptech) {
1604 y = sub0->size.y + step * (i + 1);
1605 } else {
1606 y = sub0->size.y + sub0->size.h / 2;
1607 }
1608
1609 create_line(store->targets[i]->dst->surface,
1610 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1611 y,
1612 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1613 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1614 line_color);
1615 create_line(store->targets[i]->dst->surface,
1616 sub0->size.x + sub0->size.w,
1617 y,
1618 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1619 y,
1620 line_color);
1621 }
1622
1623 if (sub1) {
1624 int y;
1625
1626 if (sub1 == ptech) {
1627 y = sub1->size.y + step * (i + 1);
1628 } else {
1629 y = sub1->size.y + sub1->size.h / 2;
1630 }
1631
1632 create_line(store->targets[i]->dst->surface,
1633 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1634 y,
1635 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1636 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1637 line_color);
1638 create_line(store->targets[i]->dst->surface,
1639 sub1->size.x + sub1->size.w,
1640 y,
1641 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1642 y,
1643 line_color);
1644 }
1645 }
1646
1647 /* Redraw rest */
1649
1650 widget_flush(pwindow);
1651}
1652
1653/**********************************************************************/
1657{
1659 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1660
1661 if (store->show_full_tree) {
1662 pwidget->theme2 = current_theme->up_icon;
1663 } else {
1664 pwidget->theme2 = current_theme->down_icon;
1665 }
1666 store->show_full_tree = !store->show_full_tree;
1667 popup_tech_info(MAX_ID - store->dock->prev->id);
1668 }
1669
1670 return -1;
1671}
1672
1673/**********************************************************************/
1677 struct widget *pwindow,
1678 struct techs_buttons *store)
1679{
1681 struct widget *pwidget;
1682 struct widget *ptech;
1683 utf8_str *pstr;
1684 SDL_Surface *surf;
1685 struct widget *dock = store->dock;
1686
1688 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1689
1692 pwidget = create_icon2(surf, pwindow->dst,
1694
1695 set_wstate(pwidget, FC_WS_NORMAL);
1697 pwidget->id = MAX_ID - tech;
1698 widget_add_as_prev(pwidget, dock);
1699 ptech = pwidget;
1700 dock = pwidget;
1701
1702 req_count = 0;
1703 for (i = AR_ONE; i <= AR_TWO; i++) {
1706
1707 if (NULL != vap && A_NONE != ar) {
1710 pwidget = create_icon2(surf, pwindow->dst,
1712 set_wstate(pwidget, FC_WS_NORMAL);
1713 pwidget->action = change_tech_callback;
1714 pwidget->id = MAX_ID - ar;
1715 widget_add_as_prev(pwidget, dock);
1716 dock = pwidget;
1717 store->requirement_button[req_count++] = pwidget;
1718 }
1719 }
1720
1721 sub_req_count = 0;
1722
1723 if (store->show_full_tree && req_count > 0) {
1724 int j, sub_tech;
1725
1726 for (j = 0; j < req_count; j++) {
1727 sub_tech = MAX_ID - store->requirement_button[j]->id;
1728 for (i = AR_ONE; i <= AR_TWO; i++) {
1731
1732 if (NULL != vap && A_NONE != ar) {
1735 pwidget = create_icon2(surf, pwindow->dst,
1737 set_wstate(pwidget, FC_WS_NORMAL);
1738 pwidget->action = change_tech_callback;
1739 pwidget->id = MAX_ID - ar;
1740 widget_add_as_prev(pwidget, dock);
1741 dock = pwidget;
1742 store->sub_req[sub_req_count++] = pwidget;
1743 }
1744 }
1745 }
1746 }
1747
1748 if (sub_req_count < 4) {
1749 store->sub_req[sub_req_count] = NULL;
1750 }
1751
1752 targets_count = 0;
1754 if ((targets_count < 6)
1755 && (advance_required(aidx, AR_ONE) == tech
1756 || advance_required(aidx, AR_TWO) == tech)) {
1759 pwidget = create_icon2(surf, pwindow->dst,
1761
1762 set_wstate(pwidget, FC_WS_NORMAL);
1763 pwidget->action = change_tech_callback;
1764 pwidget->id = MAX_ID - aidx;
1765 widget_add_as_prev(pwidget, dock);
1766 dock = pwidget;
1767 store->targets[targets_count++] = pwidget;
1768 }
1770 if (targets_count < 6) {
1771 store->targets[targets_count] = NULL;
1772 }
1773
1775 if (targets_count > 0) {
1776 int sub_tech;
1777
1778 for (i = 0; i < targets_count; i++) {
1779 sub_tech = MAX_ID - store->targets[i]->id;
1780 if (advance_required(sub_tech, AR_ONE) == tech
1783 } else if (advance_required(sub_tech, AR_TWO) == tech
1786 } else {
1787 continue;
1788 }
1789
1792 pwidget = create_icon2(surf, pwindow->dst,
1794 set_wstate(pwidget, FC_WS_NORMAL);
1795 pwidget->action = change_tech_callback;
1796 pwidget->id = MAX_ID - sub_tech;
1797 widget_add_as_prev(pwidget, dock);
1798 dock = pwidget;
1799 store->sub_targets[sub_targets_count++] = pwidget;
1800 }
1801 }
1802 if (sub_targets_count < 6) {
1804 }
1805
1807
1808 /* ------------------------------------------ */
1809 if (sub_req_count > 0) {
1810 w = (adj_size(20) + store->sub_req[0]->size.w) * 2;
1811 w += (pwindow->size.w - (20 + store->sub_req[0]->size.w + w + ptech->size.w)) / 2;
1812 } else {
1813 if (req_count > 0) {
1814 w = (pwindow->area.x + 1
1815 + width + store->requirement_button[0]->size.w * 2 + adj_size(20));
1816 w += (pwindow->size.w - ((adj_size(20) + store->requirement_button[0]->size.w)
1817 + w + ptech->size.w)) / 2;
1818 } else {
1819 w = (pwindow->size.w - ptech->size.w) / 2;
1820 }
1821 }
1822
1823 ptech->size.x = pwindow->size.x + w;
1824 ptech->size.y = pwindow->area.y + (pwindow->area.h - ptech->size.h) / 2;
1825
1826 if (req_count > 0) {
1827 h = (req_count == 1 ? store->requirement_button[0]->size.h :
1828 req_count * (store->requirement_button[0]->size.h + adj_size(80)) - adj_size(80));
1829 h = ptech->size.y + (ptech->size.h - h) / 2;
1830 for (i = 0; i < req_count; i++) {
1831 store->requirement_button[i]->size.x
1832 = ptech->size.x - adj_size(20) - store->requirement_button[i]->size.w;
1833 store->requirement_button[i]->size.y = h;
1834 h += (store->requirement_button[i]->size.h + adj_size(80));
1835 }
1836 }
1837
1838 if (sub_req_count > 0) {
1839 h = (sub_req_count == 1 ? store->sub_req[0]->size.h :
1840 sub_req_count * (store->sub_req[0]->size.h + adj_size(20)) - adj_size(20));
1841 h = ptech->size.y + (ptech->size.h - h) / 2;
1842 for (i = 0; i < sub_req_count; i++) {
1843 store->sub_req[i]->size.x
1844 = ptech->size.x - (adj_size(20) + store->sub_req[i]->size.w) * 2;
1845 store->sub_req[i]->size.y = h;
1846 h += (store->sub_req[i]->size.h + adj_size(20));
1847 }
1848 }
1849
1850 if (targets_count > 0) {
1851 h = (targets_count == 1 ? store->targets[0]->size.h :
1852 targets_count * (store->targets[0]->size.h + adj_size(20)) - adj_size(20));
1853 h = ptech->size.y + (ptech->size.h - h) / 2;
1854 for (i = 0; i < targets_count; i++) {
1855 store->targets[i]->size.x = ptech->size.x + ptech->size.w + adj_size(20);
1856 store->targets[i]->size.y = h;
1857 h += (store->targets[i]->size.h + adj_size(20));
1858 }
1859 }
1860
1861 if (sub_targets_count > 0) {
1862 if (sub_targets_count < 3) {
1863 store->sub_targets[0]->size.x
1864 = ptech->size.x + ptech->size.w - store->sub_targets[0]->size.w;
1865 store->sub_targets[0]->size.y
1866 = ptech->size.y - store->sub_targets[0]->size.h - adj_size(10);
1867 if (store->sub_targets[1]) {
1868 store->sub_targets[1]->size.x
1869 = ptech->size.x + ptech->size.w - store->sub_targets[1]->size.w;
1870 store->sub_targets[1]->size.y = ptech->size.y + ptech->size.h + adj_size(10);
1871 }
1872 } else {
1873 if (sub_targets_count < 5) {
1874 for (i = 0; i < MIN(sub_targets_count, 4); i++) {
1875 store->sub_targets[i]->size.x
1876 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1877 if (i < 2) {
1878 store->sub_targets[i]->size.y
1879 = ptech->size.y - (store->sub_targets[i]->size.h + adj_size(5)) * (2 - i);
1880 } else {
1881 store->sub_targets[i]->size.y
1882 = ptech->size.y + ptech->size.h + adj_size(5)
1883 + (store->sub_targets[i]->size.h + adj_size(5)) * (i - 2);
1884 }
1885 }
1886 } else {
1887 h = (store->sub_targets[0]->size.h + adj_size(6));
1888 for (i = 0; i < MIN(sub_targets_count, 6); i++) {
1889 switch (i) {
1890 case 0:
1891 store->sub_targets[i]->size.x
1892 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1893 store->sub_targets[i]->size.y = ptech->size.y - h * 2;
1894 break;
1895 case 1:
1896 store->sub_targets[i]->size.x
1897 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1898 - adj_size(10);
1899 store->sub_targets[i]->size.y = ptech->size.y - h - h / 2;
1900 break;
1901 case 2:
1902 store->sub_targets[i]->size.x
1903 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1904 store->sub_targets[i]->size.y = ptech->size.y - h;
1905 break;
1906 case 3:
1907 store->sub_targets[i]->size.x
1908 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1909 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6);
1910 break;
1911 case 4:
1912 store->sub_targets[i]->size.x
1913 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1914 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6) + h;
1915 break;
1916 default:
1917 store->sub_targets[i]->size.x
1918 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1919 - adj_size(10);
1920 store->sub_targets[i]->size.y
1921 = ptech->size.y + ptech->size.h + adj_size(6) + h / 2 ;
1922 break;
1923 }
1924 }
1925 }
1926 }
1927 }
1928
1929 return pwidget;
1930}
1931
1932/**********************************************************************/
1936{
1937 struct widget *pwindow;
1938 struct techs_buttons *store;
1939 struct widget *close_button = NULL;
1940 struct widget *advance_label = NULL;
1941 struct widget *list_toggle_button = NULL;
1942 struct widget *dock;
1943 utf8_str *title;
1944 utf8_str *pstr;
1945 SDL_Surface *surf;
1946 int h, tech_count;
1947 bool created;
1948 int scrollbar_width = 0;
1949 SDL_Rect area;
1950
1951 if (current_help_dlg != HELP_TECH) {
1953 }
1954
1955 /* Create new dialog if it doesn't exist yet */
1956 if (!help_dlg) {
1958 created = TRUE;
1959
1960 /* Create dialog */
1961 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
1962 store = fc_calloc(1, sizeof(struct techs_buttons));
1963
1964 store->show_tree = FALSE;
1965 store->show_full_tree = FALSE;
1966
1967 /* Create window */
1968 title = create_utf8_from_char_fonto(_("Help : Advances Tree"),
1970 title->style |= TTF_STYLE_BOLD;
1971
1973 pwindow->data.ptr = (void *)store;
1975 set_wstate(pwindow, FC_WS_NORMAL);
1976
1977 add_to_gui_list(ID_WINDOW, pwindow);
1978
1979 help_dlg->end_widget_list = pwindow;
1980
1981 /* ------------------ */
1982
1983 /* Close button */
1984 close_button = create_themeicon(current_theme->small_cancel_icon, pwindow->dst,
1987 close_button->info_label
1988 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
1989 close_button->action = exit_help_dlg_callback;
1990 set_wstate(close_button, FC_WS_NORMAL);
1991 close_button->key = SDLK_ESCAPE;
1992
1993 add_to_gui_list(ID_BUTTON, close_button);
1994
1995 /* ------------------ */
1996 dock = close_button;
1997
1998 /* --- Create scrollable advance list on the left side ---*/
2000 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
2001
2002 tech_count = 0;
2005
2006 if (vap) {
2009 advance_label = create_icon2(surf, pwindow->dst,
2011
2015
2016 if (tech_count++ >= 10) {
2018 }
2019 }
2021
2023
2027
2028 if (tech_count > 10) {
2031 }
2032
2033 /* Toggle techs list button */
2035 current_theme->up_icon,
2036 pwindow->dst,
2037 _("Advances"),
2038 FONTO_DEFAULT, 0);
2040 if (store->show_tree) {
2042 }
2045
2047
2048 dock = list_toggle_button;
2049 store->dock = dock;
2050 } else {
2051 created = FALSE;
2053 pwindow = help_dlg->end_widget_list;
2054 store = (struct techs_buttons *)pwindow->data.ptr;
2055 dock = store->dock;
2056
2057 /* Delete any previous list entries */
2061 }
2062
2063 /* Show/hide techs list */
2065
2066 if (store->show_tree) {
2068 } else {
2070 }
2071
2072 if (store->show_full_tree) {
2073 /* All entries are visible without scrolling */
2077 } else {
2078 int count = help_dlg->scroll->active;
2079
2081 while (advance_label->prev != NULL && --count > 0) {
2083 }
2086 }
2087 }
2088
2089 /* --------------------------------------------------------- */
2090 if (created) {
2091
2093 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
2094 FREESURFACE(surf);
2095 }
2096
2097 area = pwindow->area;
2098
2099 widget_set_position(pwindow,
2100 (main_window_width() - pwindow->size.w) / 2,
2101 (main_window_height() - pwindow->size.h) / 2);
2102
2103 /* Exit button */
2104 close_button = pwindow->prev;
2105 widget_set_position(close_button,
2106 area.x + area.w - close_button->size.w - 1,
2107 pwindow->size.y + adj_size(2));
2108
2109 /* List toggle button */
2110 list_toggle_button = store->dock;
2111 widget_set_position(list_toggle_button, area.x, area.y);
2112
2113 /* List entries */
2115 area.y + list_toggle_button->size.h, 0, 0,
2118 /* Scrollbar */
2119 if (help_dlg->scroll) {
2121 area.x, area.y + list_toggle_button->size.h,
2122 h, FALSE);
2123 }
2124 }
2125
2126 if (store->show_tree) {
2129 } else {
2132 }
2133}
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:662
struct civclient client
char * incite_cost
Definition comments.c:74
QString current_theme
Definition fc_client.cpp:65
int Tech_type_id
Definition fc_types.h:380
int Impr_type_id
Definition fc_types.h:379
int Unit_type_id
Definition fc_types.h:385
@ O_SHIELD
Definition fc_types.h:101
@ O_FOOD
Definition fc_types.h:101
@ O_GOLD
Definition fc_types.h:101
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * government_name_translation(const struct government *pgovern)
Definition government.c:143
Government_type_id government_index(const struct government *pgovern)
Definition government.c:82
#define governments_iterate(NAME_pgov)
Definition government.h:120
#define governments_iterate_end
Definition government.h:123
GtkWidget * unit_info_label
Definition gui_main.c:151
static void create_tech_tree(int tech, int levels, GtkTreeIter *parent)
Definition helpdlg.c:226
void popdown_help_dialog(void)
Definition helpdlg.c:186
void popup_help_dialog_string(const char *item)
Definition helpdlg.c:212
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Definition helpdlg.c:196
void flush_dirty(void)
Definition mapview.c:468
const char * title
Definition repodlgs.c:1314
SDL_Color * get_theme_color(enum theme_color themecolor)
Definition colors.c:47
int main_window_width(void)
Definition graphics.c:685
int fill_rect_alpha(SDL_Surface *surf, SDL_Rect *prect, SDL_Color *pcolor)
Definition graphics.c:865
void create_line(SDL_Surface *dest, Sint16 x0, Sint16 y0, Sint16 x1, Sint16 y1, SDL_Color *pcolor)
Definition graphics.c:1379
SDL_Surface * copy_surface(SDL_Surface *src)
Definition graphics.c:1309
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:199
struct sdl2_data main_data
Definition graphics.c:57
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:351
void create_frame(SDL_Surface *dest, Sint16 left, Sint16 top, Sint16 width, Sint16 height, SDL_Color *pcolor)
Definition graphics.c:1348
int main_window_height(void)
Definition graphics.c:693
SDL_Surface * resize_surface_box(const SDL_Surface *psrc, Uint16 new_width, Uint16 new_height, int smooth, bool scale_up, bool absolute_dimensions)
Definition graphics.c:1257
#define FREESURFACE(ptr)
Definition graphics.h:322
#define adj_surf(surf)
Definition graphics.h:200
#define map_rgba(format, color)
Definition graphics.h:315
@ ID_BUTTON
Definition gui_id.h:29
@ ID_LABEL
Definition gui_id.h:27
@ ID_WINDOW
Definition gui_id.h:30
#define adj_size(size)
Definition gui_main.h:141
#define PRESSED_EVENT(event)
Definition gui_main.h:71
utf8_str * copy_chars_to_utf8_str(utf8_str *pstr, const char *pchars)
Definition gui_string.c:251
SDL_Surface * create_text_surf_from_utf8(utf8_str *pstr)
Definition gui_string.c:425
void change_fonto_utf8(utf8_str *pstr, enum font_origin origin)
Definition gui_string.c:584
utf8_str * create_utf8_str_fonto(char *in_text, size_t n_alloc, enum font_origin origin)
Definition gui_string.c:241
bool convert_utf8_str_to_const_surface_width(utf8_str *pstr, int width)
Definition gui_string.c:449
SDL_Surface * create_text_surf_smaller_than_w(utf8_str *pstr, int w)
Definition gui_string.c:539
#define FREEUTF8STR(pstr)
Definition gui_string.h:93
#define SF_CENTER
Definition gui_string.h:40
@ FONTO_HEADING
Definition gui_string.h:69
@ FONTO_DEFAULT
Definition gui_string.h:65
@ FONTO_ATTENTION
Definition gui_string.h:67
@ FONTO_MAX
Definition gui_string.h:71
#define create_utf8_from_char_fonto(string_in, fonto)
Definition gui_string.h:108
SDL_Color * get_tech_color(Tech_type_id tech_id)
SDL_Surface * get_tech_icon(Tech_type_id tech)
static SDL_Surface * get_government_surface(const struct government *gov)
static SDL_Surface * get_building_surface(const struct impr_type *pimprove)
static SDL_Surface * get_unittype_surface(const struct unit_type *punittype, enum direction8 facing)
static int exit_help_dlg_callback(struct widget *pwidget)
Definition helpdlg.c:130
void popup_gov_info(int gov)
Definition helpdlg.c:155
void popup_tech_info(Tech_type_id tech)
Definition helpdlg.c:1935
static const int bufsz
Definition helpdlg.c:70
static struct advanced_dialog * help_dlg
Definition helpdlg.c:52
static int show_tech_tree_callback(struct widget *pwidget)
Definition helpdlg.c:1041
enum help_page_type current_help_dlg
Definition helpdlg.c:68
static void redraw_tech_info_dlg(void)
Definition helpdlg.c:1060
static void redraw_unit_info_dlg(void)
Definition helpdlg.c:604
static int change_tech_callback(struct widget *pwidget)
Definition helpdlg.c:1029
void popup_help_browser(void)
Definition helpdlg.c:77
static struct widget * create_tech_info(Tech_type_id tech, int width, struct widget *pwindow, struct techs_buttons *store)
Definition helpdlg.c:1133
void popup_impr_info(Impr_type_id impr)
Definition helpdlg.c:202
static void redraw_tech_tree_dlg(void)
Definition helpdlg.c:1414
static int help_dlg_window_callback(struct widget *pwindow)
Definition helpdlg.c:122
static int change_unit_callback(struct widget *pwidget)
Definition helpdlg.c:592
void popup_unit_info(Unit_type_id type_id)
Definition helpdlg.c:632
static int change_gov_callback(struct widget *pwidget)
Definition helpdlg.c:143
static void redraw_impr_info_dlg(void)
Definition helpdlg.c:174
static int toggle_full_tree_mode_in_help_dlg_callback(struct widget *pwidget)
Definition helpdlg.c:1656
static int change_impr_callback(struct widget *pwidget)
Definition helpdlg.c:162
SDL_Surface * create_select_tech_icon(utf8_str *pstr, Tech_type_id tech_id, enum tech_info_mode mode)
Definition repodlgs.c:2423
@ TIM_SMALL_MODE
Definition repodlgs.h:32
@ TIM_FULL_MODE
Definition repodlgs.h:30
SDL_Surface * theme_get_background(const struct theme *t, enum theme_background background)
@ BACKGROUND_HELPDLG
@ COLOR_THEME_HELPDLG_FRAME
Definition themecolors.h:86
@ COLOR_THEME_HELPDLG_TEXT
Definition themecolors.h:90
@ COLOR_THEME_HELPDLG_LINE3
Definition themecolors.h:89
@ COLOR_THEME_CITYDLG_LUX
Definition themecolors.h:59
@ COLOR_THEME_HELPDLG_LINE
Definition themecolors.h:87
@ COLOR_THEME_HELPDLG_LINE2
Definition themecolors.h:88
struct theme * active_theme
Definition themespec.c:154
void add_to_gui_list(Uint16 id, struct widget *gui)
Definition widget.c:586
void del_group_of_widgets_from_gui_list(struct widget *begin_group_widget_list, struct widget *end_group_widget_list)
Definition widget.c:863
void show_group(struct widget *begin_group_widget_list, struct widget *end_group_widget_list)
Definition widget.c:934
void hide_group(struct widget *begin_group_widget_list, struct widget *end_group_widget_list)
Definition widget.c:915
void widget_add_as_prev(struct widget *new_widget, struct widget *add_dock)
Definition widget.c:602
int setup_vertical_widgets_position(int step, Sint16 start_x, Sint16 start_y, Uint16 w, Uint16 h, struct widget *begin, struct widget *end)
Definition widget.c:1051
Uint16 redraw_group(const struct widget *begin_group_widget_list, const struct widget *end_group_widget_list, int add_to_update)
Definition widget.c:720
void popdown_window_group_dialog(struct widget *begin_group_widget_list, struct widget *end_group_widget_list)
Definition widget.c:983
static void widget_set_position(struct widget *pwidget, int x, int y)
Definition widget.h:266
#define MAX_ID
Definition widget.h:38
@ FC_WS_DISABLED
Definition widget.h:99
@ FC_WS_NORMAL
Definition widget.h:96
static void widget_flush(struct widget *pwidget)
Definition widget.h:291
void set_wstate(struct widget *pwidget, enum widget_state state)
Definition widget_core.c:36
@ WF_WIDGET_HAS_INFO_LABEL
Definition widget.h:88
@ WF_FREE_DATA
Definition widget.h:78
@ WF_SELECT_WITHOUT_BAR
Definition widget.h:89
@ WF_RESTORE_BACKGROUND
Definition widget.h:85
@ WF_HIDDEN
Definition widget.h:68
@ WF_FREE_THEME
Definition widget.h:72
static void widget_resize(struct widget *pwidget, int w, int h)
Definition widget.h:271
void set_wflag(struct widget *pwidget, enum widget_flag flag)
Definition widget_core.c:54
#define create_themeicon_button_from_chars_fonto(icon_theme, pdest, char_string, fonto, flags)
struct widget * create_themeicon(SDL_Surface *icon_theme, struct gui_layer *pdest, Uint32 flags)
struct widget * create_icon2(SDL_Surface *icon, struct gui_layer *pdest, Uint32 flags)
struct widget * create_iconlabel(SDL_Surface *icon, struct gui_layer *pdest, utf8_str *pstr, Uint32 flags)
#define create_iconlabel_from_chars_fonto(picon, pdest, chars, fonto, flags)
void setup_vertical_scrollbar_area(struct scroll_bar *scroll, Sint16 start_x, Sint16 start_y, Uint16 height, bool swap_start_x)
Uint32 create_vertical_scrollbar(struct advanced_dialog *dlg, Uint8 step, Uint8 active, bool create_scrollbar, bool create_buttons)
#define hide_scrollbar(scrollbar)
#define show_scrollbar(scrollbar)
bool resize_window(struct widget *pwindow, SDL_Surface *bcgd, SDL_Color *pcolor, Uint16 new_w, Uint16 new_h)
struct widget * create_window_skeleton(struct gui_layer *pdest, utf8_str *title, Uint32 flags)
void helptext_advance(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, int i)
Definition helpdata.c:3268
char * helptext_building(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct impr_type *pimprove)
Definition helpdata.c:1381
char * helptext_unit(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct unit_type *utype)
Definition helpdata.c:1865
help_page_type
Definition helpdlg_g.h:20
@ HELP_ANY
Definition helpdlg_g.h:20
@ HELP_LAST
Definition helpdlg_g.h:25
@ HELP_IMPROVEMENT
Definition helpdlg_g.h:20
@ HELP_UNIT
Definition helpdlg_g.h:20
@ HELP_TECH
Definition helpdlg_g.h:21
const struct impr_type * valid_improvement(const struct impr_type *pimprove)
struct impr_type * improvement_by_number(const Impr_type_id id)
int impr_base_build_shield_cost(const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_convert_improvement(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define log_debug(message,...)
Definition log.h:115
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1015
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
int step
Definition specpq.h:92
struct sprite int int y
Definition sprite_g.h:31
struct widget * begin_active_widget_list
Definition widget.h:184
struct widget * end_widget_list
Definition widget.h:182
struct widget * end_active_widget_list
Definition widget.h:185
struct widget * active_widget_list
Definition widget.h:186
struct scroll_bar * scroll
Definition widget.h:187
struct widget * begin_widget_list
Definition widget.h:181
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:151
SDL_Surface * surface
Definition graphics.h:229
Definition climisc.h:80
struct widget * up_left_button
SDL_Event event
Definition graphics.h:217
struct widget * targets[6]
Definition helpdlg.c:55
struct widget * requirement_button[2]
Definition helpdlg.c:56
struct widget * sub_req[4]
Definition helpdlg.c:56
bool show_tree
Definition helpdlg.c:58
struct widget * dock
Definition helpdlg.c:57
struct widget * sub_targets[6]
Definition helpdlg.c:55
bool show_full_tree
Definition helpdlg.c:59
const struct unit_type * obsoleted_by
Definition unittype.h:529
struct widget * obsolete_by_button
Definition helpdlg.c:63
struct widget * requirement_button
Definition helpdlg.c:64
struct widget * dock
Definition helpdlg.c:65
SDL_Color fgcol
Definition gui_string.h:57
void * ptr
Definition widget.h:133
SDL_Keycode key
Definition widget.h:153
union widget::@192 data
SDL_Surface * theme2
Definition widget.h:119
struct widget * prev
Definition widget.h:114
struct gui_layer * dst
Definition widget.h:116
Uint16 mod
Definition widget.h:154
utf8_str * string_utf8
Definition widget.h:121
int(* action)(struct widget *)
Definition widget.h:157
SDL_Rect area
Definition widget.h:149
struct widget * next
Definition widget.h:113
utf8_str * info_label
Definition widget.h:122
Uint16 id
Definition widget.h:155
SDL_Rect size
Definition widget.h:145
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:290
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:121
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define advance_index_iterate_end
Definition tech.h:248
@ AR_TWO
Definition tech.h:112
@ AR_ONE
Definition tech.h:111
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_index_iterate(_start, _index)
Definition tech.h:244
bool is_tech_req_for_utype(const struct unit_type *ptype, struct advance *padv)
Definition unittype.c:2710
int utype_build_shield_cost_base(const struct unit_type *punittype)
Definition unittype.c:1468
struct advance * utype_primary_tech_req(const struct unit_type *ptype)
Definition unittype.c:2696
Unit_type_id utype_count(void)
Definition unittype.c:80
struct unit_type * utype_by_number(const Unit_type_id id)
Definition unittype.c:112
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
#define unit_type_iterate(_p)
Definition unittype.h:852
#define unit_type_iterate_end
Definition unittype.h:859
#define U_NOT_OBSOLETED
Definition unittype.h:528