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/* SDL3 */
19#include <SDL3/SDL.h>
20
21/* utility */
22#include "fcintl.h"
23#include "log.h"
24
25/* common */
26#include "game.h"
27#include "government.h"
28#include "movement.h"
29
30/* client */
31#include "client_main.h"
32#include "helpdata.h"
33
34/* gui-sdl3 */
35#include "colors.h"
36#include "graphics.h"
37#include "gui_id.h"
38#include "gui_main.h"
39#include "gui_tilespec.h"
40#include "mapview.h"
41#include "repodlgs.h"
42#include "sprite.h"
43#include "themespec.h"
44#include "widget.h"
45
46#include "helpdlg.h"
47
48static struct advanced_dialog *help_dlg = NULL;
49
50struct techs_buttons {
51 struct widget *targets[6], *sub_targets[6];
52 struct widget *requirement_button[2], *sub_req[4];
53 struct widget *dock;
54 bool show_tree;
55 bool show_full_tree;
56};
57
58struct units_buttons {
61 struct widget *dock;
62};
63
65
66static const int bufsz = 8192;
67
68static int change_tech_callback(struct widget *pwidget);
69
70/**********************************************************************/
77
78/**********************************************************************/
89
90/**********************************************************************/
97{
98 log_debug("popup_help_dialog_typed : PORT ME");
99}
100
101/**********************************************************************/
114
115/**********************************************************************/
118static int help_dlg_window_callback(struct widget *pwindow)
119{
120 return -1;
121}
122
123/**********************************************************************/
126static int exit_help_dlg_callback(struct widget *pwidget)
127{
130 flush_dirty();
131 }
132
133 return -1;
134}
135
136/**********************************************************************/
139static int change_gov_callback(struct widget *pwidget)
140{
142 popup_gov_info(MAX_ID - pwidget->id);
143 }
144
145 return -1;
146}
147
148/**********************************************************************/
151void popup_gov_info(int gov)
152{
153}
154
155/**********************************************************************/
158static int change_impr_callback(struct widget *pwidget)
159{
161 popup_impr_info(MAX_ID - pwidget->id);
162 }
163
164 return -1;
165}
166
167/**********************************************************************/
170static void redraw_impr_info_dlg(void)
171{
172 SDL_Color bg_color = {255, 255, 255, 64};
173 struct widget *pwindow = help_dlg->end_widget_list;
174 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
175 SDL_Rect dst;
176
177 redraw_group(pwindow->prev, pwindow, FALSE);
178
179 dst.x = store->dock->prev->size.x - adj_size(10);
180 dst.y = store->dock->prev->size.y - adj_size(10);
181 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
182 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
183
184 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
185
186 create_frame(pwindow->dst->surface,
187 dst.x, dst.y, dst.w, dst.h,
189
190 /*------------------------------------- */
192 widget_flush(pwindow);
193}
194
195/**********************************************************************/
199{
200 SDL_Color bg_color = {255, 255, 255, 128};
201 struct widget *pwindow;
202 struct units_buttons *store;
203 struct widget *close_button = NULL;
206 struct widget *impr_name_label = NULL;
207 struct widget *cost_label = NULL;
208 struct widget *upkeep_label = NULL;
209 struct widget *requirement_label = NULL;
211 struct widget *obsolete_by_label = NULL;
213 struct widget *help_text_label = NULL;
214 struct widget *dock;
216 utf8_str *pstr;
217 SDL_Surface *surf;
218 int h, start_x, start_y, impr_type_count;
219 bool created, text = FALSE;
220 int scrollbar_width = 0;
221 struct impr_type *pimpr_type;
222 char buffer[64000];
223 SDL_Rect area;
224 struct advance *obsTech = NULL;
225
228 }
229
230 if (!help_dlg) {
231 SDL_Surface *background_tmpl, *background, *impr_name, *icon;
232 SDL_Rect dst;
233
235 created = TRUE;
236
237 /* Create dialog */
238 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
239 store = fc_calloc(1, sizeof(struct units_buttons));
240
241 /* Create window */
242 title = create_utf8_from_char_fonto(_("Help : Improvements"),
244 title->style |= TTF_STYLE_BOLD;
245
248 set_wstate(pwindow , FC_WS_NORMAL);
249 pwindow->data.ptr = (void *)store;
250 add_to_gui_list(ID_WINDOW, pwindow);
251
252 help_dlg->end_widget_list = pwindow;
253
254 area = pwindow->area;
255 /* ------------------ */
256
257 /* Close button */
258 close_button = create_themeicon(current_theme->small_cancel_icon,
259 pwindow->dst,
262 close_button->info_label
263 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"),
265 close_button->action = exit_help_dlg_callback;
266 set_wstate(close_button, FC_WS_NORMAL);
267 close_button->key = SDLK_ESCAPE;
268
269 add_to_gui_list(ID_BUTTON, close_button);
270
271 /* ------------------ */
272 dock = close_button;
273
275 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
276
277 /* Background template for entries in scroll list */
281
283 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
285
286 impr_type_count = 0;
287 improvement_iterate(pimprove) {
288
289 /* Copy background surface */
290 background = copy_surface(background_tmpl);
291
292 /* Blit improvement name */
295 dst.x = adj_size(40) + (background->w - impr_name->w - adj_size(40)) / 2;
296 dst.y = (background->h - impr_name->h) / 2;
297 alphablit(impr_name, NULL, background, &dst, 255);
299
300 /* Blit improvement icon */
302 adj_size(36), adj_size(36), 1, TRUE, TRUE);
303 dst.x = adj_size(5);
304 dst.y = (background->h - icon->h) / 2;
305 alphablit(icon, NULL, background, &dst, 255);
306 FREESURFACE(icon);
307
308 improvement_button = create_icon2(background, pwindow->dst,
310
314
315 if (impr_type_count++ >= 10) {
317 }
318
320
322
326
327 if (impr_type_count > 10) {
330 }
331
332 /* Toggle techs list button */
334 current_theme->up_icon,
335 pwindow->dst,
336 _("Improvements"),
337 FONTO_DEFAULT, 0);
338#if 0
340 if (store->show_tree) {
342 }
343#endif
344
347
349
350 dock = list_toggle_button;
351 store->dock = dock;
352 } else {
353 created = FALSE;
355 pwindow = help_dlg->end_widget_list;
356 store = (struct units_buttons *)pwindow->data.ptr;
357 dock = store->dock;
358
359 area = pwindow->area;
360
361 /* Delete any previous list entries */
364 dock->prev);
366 }
367 }
368
370
374 adj_size(48), 1, TRUE, TRUE),
375 pwindow->dst,
378
382
384 sprintf(buffer, "%s %d", _("Base Cost:"),
387 buffer,
388 FONTO_ATTENTION, 0);
389 cost_label->id = ID_LABEL;
392
393 if (!is_wonder(pimpr_type)) {
394 sprintf(buffer, "%s %d", _("Upkeep:"), pimpr_type->upkeep);
396 buffer,
397 FONTO_ATTENTION, 0);
401 }
402 }
403
404 /* Requirement */
406 _("Requirement:"),
407 FONTO_ATTENTION, 0);
411
412 /* FIXME: this should show ranges, negated reqs, and all the
413 * MAX_NUM_REQS reqs.
414 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
415 * definition. */
417 if (!preq->present) {
418 continue;
419 }
422 universal_name_translation(&preq->source, buffer, sizeof(buffer)),
425 if (preq->source.kind != VUT_ADVANCE) {
426 break; /* FIXME */
427 }
428 requirement_label2->id = MAX_ID - advance_number(preq->source.value.advance);
429 requirement_label2->string_utf8->fgcol
430 = *get_tech_color(advance_number(preq->source.value.advance));
433 break;
435
436 if (requirement_label2 == NULL) {
438 Q_("?req:None"),
439 FONTO_ATTENTION, 0);
441 }
442
446
447 /* Obsolete by */
449 _("Obsolete by:"),
450 FONTO_ATTENTION, 0);
454
456 if (pobs->source.kind == VUT_ADVANCE) {
457 obsTech = pobs->source.value.advance;
458 break;
459 }
461
462 if (obsTech == NULL) {
464 _("Never"),
465 FONTO_ATTENTION, 0);
467 } else {
474 obsolete_by_label2->string_utf8->fgcol
478 }
482
483 /* Helptext */
484 start_x = (area.x + 1 + scrollbar_width + help_dlg->end_active_widget_list->size.w + adj_size(20));
485
486 buffer[0] = '\0';
487 helptext_building(buffer, sizeof(buffer), client.conn.playing, NULL,
488 pimpr_type);
489 if (buffer[0] != '\0') {
491
496 text = TRUE;
497 }
498
500
501 /* --------------------------------------------------------- */
502 if (created) {
504 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
505 FREESURFACE(surf);
506 }
507
508 area = pwindow->area;
509
510 widget_set_position(pwindow,
511 (main_window_width() - pwindow->size.w) / 2,
512 (main_window_height() - pwindow->size.h) / 2);
513
514 /* Exit button */
515 close_button = pwindow->prev;
516 widget_set_position(close_button,
517 area.x + area.w - close_button->size.w - 1,
518 pwindow->size.y + adj_size(2));
519
520 /* List toggle button */
521 list_toggle_button = store->dock;
523
524 /* List entries */
526 area.y + list_toggle_button->size.h, 0, 0,
529
530 /* Scrollbar */
531 if (help_dlg->scroll) {
533 area.x, area.y + list_toggle_button->size.h,
534 h, FALSE);
535 }
536 }
537
538 impr_name_label = store->dock->prev;
539 widget_set_position(impr_name_label, start_x, area.y + adj_size(16));
540
541 start_y = impr_name_label->size.y + impr_name_label->size.h + adj_size(10);
542
546 if (!is_wonder(pimpr_type)) {
547 upkeep_label = cost_label->prev;
549 cost_label->size.x + cost_label->size.w + adj_size(20),
550 start_y);
551 }
552 start_y += cost_label->size.h;
553 }
554
557
560 requirement_label->size.x + requirement_label->size.w + adj_size(5),
561 start_y);
562
563 if (store->obsolete_by_button) {
566 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
567 start_y);
568
571 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
572 start_y);
573
574 start_y += obsolete_by_label2->size.h;
575 }
576
577 start_y += adj_size(30);
578
579 if (text) {
581 }
582
584}
585
586/**********************************************************************/
589static int change_unit_callback(struct widget *pwidget)
590{
592 popup_unit_info(MAX_ID - pwidget->id);
593 }
594
595 return -1;
596}
597
598/**********************************************************************/
601static void redraw_unit_info_dlg(void)
602{
603 SDL_Color bg_color = {255, 255, 255, 64};
604 struct widget *pwindow = help_dlg->end_widget_list;
605 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
606 SDL_Rect dst;
607
608 redraw_group(pwindow->prev, pwindow, FALSE);
609
610 dst.x = store->dock->prev->size.x - adj_size(10);
611 dst.y = store->dock->prev->size.y - adj_size(10);
612 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
613 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
614
615 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
616
617 create_frame(pwindow->dst->surface,
618 dst.x, dst.y, dst.w, dst.h,
620
621 /*------------------------------------- */
623 widget_flush(pwindow);
624}
625
626/**********************************************************************/
630{
631 SDL_Color bg_color = {255, 255, 255, 128};
632 struct widget *pwindow;
633 struct units_buttons *store;
634 struct widget *close_button = NULL;
636 struct widget *unit_button = NULL;
637 struct widget *unit_name_label = NULL;
638 struct widget *unit_info_label = NULL;
639 struct widget *requirement_label = NULL;
641 struct widget *obsolete_by_label = NULL;
643 struct widget *help_text_label = NULL;
644 struct widget *dock;
646 utf8_str *pstr;
647 SDL_Surface *surf;
648 int h, start_x, start_y, utype_count;
649 bool created, text = FALSE;
650 int scrollbar_width = 0;
651 struct unit_type *punittype;
652 char buffer[bufsz];
653 SDL_Rect area;
654 struct advance *req;
655
658 }
659
660 /* Create new dialog if it doesn't exist yet */
661 if (!help_dlg) {
662 SDL_Surface *background_tmpl, *background, *unit_name, *icon;
663 SDL_Rect dst;
664
666 created = TRUE;
667
668 /* Create dialog */
669 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
670 store = fc_calloc(1, sizeof(struct units_buttons));
671
672 /* Create window */
674 title->style |= TTF_STYLE_BOLD;
675
678 set_wstate(pwindow , FC_WS_NORMAL);
679 pwindow->data.ptr = (void *)store;
680 add_to_gui_list(ID_WINDOW, pwindow);
681
682 help_dlg->end_widget_list = pwindow;
683
684 area = pwindow->area;
685
686 /* ------------------ */
687
688 /* Close button */
689 close_button = create_themeicon(current_theme->small_cancel_icon,
690 pwindow->dst,
693 close_button->info_label
694 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
695 close_button->action = exit_help_dlg_callback;
696 set_wstate(close_button, FC_WS_NORMAL);
697 close_button->key = SDLK_ESCAPE;
698
699 add_to_gui_list(ID_BUTTON, close_button);
700
701 /* ------------------ */
702 dock = close_button;
703
704 /* --- Create scrollable unit list on the left side ---*/
705
707 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
708
709 /* Background template for entries in scroll list */
713
715 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
717
718 utype_count = 0;
720
721 /* Copy background surface */
722 background = copy_surface(background_tmpl);
723
724 /* Blit unit name */
727 dst.x = adj_size(35) + (background->w - unit_name->w - adj_size(35)) / 2;
728 dst.y = (background->h - unit_name->h) / 2;
729 alphablit(unit_name, NULL, background, &dst, 255);
731
732 /* Blit unit icon */
734 adj_size(36), adj_size(36), 1, TRUE, TRUE);
735 dst.x = (adj_size(35) - icon->w) / 2;
736 dst.y = (background->h - icon->h) / 2;
737 alphablit(icon, NULL, background, &dst, 255);
738 FREESURFACE(icon);
739
740 unit_button = create_icon2(background, pwindow->dst,
742
746
747 if (utype_count++ >= 10) {
749 }
750
752
754
758
759 if (utype_count > 10) {
762 }
763
764 /* Toggle techs list button */
766 current_theme->up_icon,
767 pwindow->dst,
768 _("Units"),
769 FONTO_DEFAULT, 0);
770#if 0
772 if (store->show_tree) {
774 }
775#endif
776
779
781
782 dock = list_toggle_button;
783 store->dock = dock;
784 } else {
785 created = FALSE;
787 pwindow = help_dlg->end_widget_list;
788 store = (struct units_buttons *)pwindow->data.ptr;
789 dock = store->dock;
790
791 area = pwindow->area;
792
793 /* Delete any previous list entries */
796 dock->prev);
798 }
799 }
800
807
811
812 {
813 char buf[2048];
814
815 fc_snprintf(buf, sizeof(buf), "%s %d %s",
817 PL_("shield", "shields", utype_build_shield_cost_base(punittype)));
818
819 if (punittype->pop_cost) {
820 cat_snprintf(buf, sizeof(buf), " %d %s",
821 punittype->pop_cost, PL_("citizen", "citizens",
822 punittype->pop_cost));
823 }
824
825 cat_snprintf(buf, sizeof(buf), " %s", _("Upkeep:"));
826
827 if (punittype->upkeep[O_SHIELD]) {
828 cat_snprintf(buf, sizeof(buf), " %d %s",
829 punittype->upkeep[O_SHIELD], PL_("shield", "shields",
830 punittype->upkeep[O_SHIELD]));
831 }
832 if (punittype->upkeep[O_FOOD]) {
833 cat_snprintf(buf, sizeof(buf), " %d %s",
834 punittype->upkeep[O_FOOD], PL_("food", "foods",
835 punittype->upkeep[O_FOOD]));
836 }
837 if (punittype->upkeep[O_GOLD]) {
838 cat_snprintf(buf, sizeof(buf), " %d %s",
839 punittype->upkeep[O_GOLD], PL_("gold", "golds",
840 punittype->upkeep[O_GOLD]));
841 }
842 if (punittype->happy_cost) {
843 cat_snprintf(buf, sizeof(buf), " %d %s",
844 punittype->happy_cost, PL_("citizen", "citizens",
845 punittype->happy_cost));
846 }
847
848 cat_snprintf(buf, sizeof(buf), "\n%s %d %s %d %s %s\n%s %d %s %d %s %d",
849 _("Attack:"), punittype->attack_strength,
850 _("Defense:"), punittype->defense_strength,
851 _("Move:"), move_points_text(punittype->move_rate, TRUE),
852 _("Vision:"), punittype->vision_radius_sq,
853 _("Firepower:"), punittype->firepower,
854 _("Hitpoints:"), punittype->hp);
855
857 FONTO_ATTENTION, 0);
861 }
862
863 /* Requirement */
865 _("Requirement:"),
866 FONTO_ATTENTION, 0);
870
872
873 if (advance_number(req) == A_NONE) {
875 Q_("?tech:None"),
876 FONTO_ATTENTION, 0);
878 } else {
880
887 requirement_label2->string_utf8->fgcol = *get_tech_color(req_id);
890 }
894
895 /* Obsolete by */
897 _("Obsolete by:"),
898 FONTO_ATTENTION, 0);
902
903 if (punittype->obsoleted_by == U_NOT_OBSOLETED) {
905 Q_("?utype:None"),
906 FONTO_ATTENTION, 0);
908 } else {
909 const struct unit_type *utype = punittype->obsoleted_by;
910 struct advance *obs_req = utype_primary_tech_req(utype);
911
917 obsolete_by_label2->string_utf8->fgcol
922 }
924 dock = obsolete_by_label2;
926
927 /* Helptext */
928 start_x = (area.x + 1 + scrollbar_width + help_dlg->active_widget_list->size.w + adj_size(20));
929
930 buffer[0] = '\0';
931 helptext_unit(buffer, sizeof(buffer), client.conn.playing, "", utype_by_number(type_id),
932 TRUE);
933 if (buffer[0] != '\0') {
935
940 text = TRUE;
941 }
942
944
945 /* --------------------------------------------------------- */
946 if (created) {
947
949 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
950 FREESURFACE(surf);
951 }
952
953 area = pwindow->area;
954
955 widget_set_position(pwindow,
956 (main_window_width() - pwindow->size.w) / 2,
957 (main_window_height() - pwindow->size.h) / 2);
958
959 /* Exit button */
960 close_button = pwindow->prev;
961 widget_set_position(close_button,
962 area.x + area.w - close_button->size.w - 1,
963 pwindow->size.y + adj_size(2));
964
965 /* List toggle button */
966 list_toggle_button = store->dock;
968
969 /* List entries */
971 area.y + list_toggle_button->size.h, 0, 0,
974
975 /* Scrollbar */
976 if (help_dlg->scroll) {
978 area.x, area.y + list_toggle_button->size.h,
979 h, FALSE);
980 }
981 }
982
983 unit_name_label = store->dock->prev;
984 widget_set_position(unit_name_label, start_x, area.y + adj_size(16));
985
986 start_y = unit_name_label->size.y + unit_name_label->size.h + adj_size(10);
987
990
991 start_y += unit_info_label->size.h;
992
995
998 requirement_label->size.x + requirement_label->size.w + adj_size(5),
999 start_y);
1000
1003 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
1004 start_y);
1005
1008 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
1009 start_y);
1010
1011 start_y += obsolete_by_label2->size.h + adj_size(20);
1012
1013 if (text) {
1016 }
1017
1019}
1020
1021/* =============================================== */
1022/* ==================== Tech Tree ================ */
1023/* =============================================== */
1024
1025/**********************************************************************/
1028static int change_tech_callback(struct widget *pwidget)
1029{
1031 popup_tech_info(MAX_ID - pwidget->id);
1032 }
1033
1034 return -1;
1035}
1036
1037/**********************************************************************/
1040static int show_tech_tree_callback(struct widget *pwidget)
1041{
1043 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1044
1045 store->show_tree = !store->show_tree;
1046 if (!store->show_tree) {
1047 store->show_full_tree = FALSE;
1048 store->dock->theme2 = current_theme->up_icon;
1049 }
1050 popup_tech_info(MAX_ID - store->dock->prev->id);
1051 }
1052
1053 return -1;
1054}
1055
1056/**********************************************************************/
1059static void redraw_tech_info_dlg(void)
1060{
1061 SDL_Color bg_color = {255, 255, 255, 64};
1062 struct widget *pwindow = help_dlg->end_widget_list;
1063 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1065 utf8_str *pstr;
1066 SDL_Rect dst;
1067
1068 redraw_group(pwindow->prev, pwindow, FALSE);
1069
1070 dst.x = store->dock->prev->prev->size.x - adj_size(10);
1071 dst.y = store->dock->prev->prev->size.y - adj_size(10);
1072 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
1073 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
1074
1075 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1076
1077 create_frame(pwindow->dst->surface,
1078 dst.x, dst.y, dst.w, dst.h,
1080
1081 /* -------------------------- */
1083 pstr->style |= TTF_STYLE_BOLD;
1084
1086 dst.x = store->dock->prev->prev->size.x;
1087 if (store->targets[0]) {
1088 dst.y = store->targets[0]->size.y - text0->h;
1089 } else {
1090 dst.y = store->dock->prev->prev->size.y
1091 + store->dock->prev->prev->size.h + adj_size(10);
1092 }
1093
1094 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1096
1097 if (store->sub_targets[0]) {
1098 int i;
1099
1101
1102 copy_chars_to_utf8_str(pstr, _("( with "));
1104
1107 i = 0;
1109 dst.x = store->sub_targets[i]->size.x - text0->w;
1110 dst.y = store->sub_targets[i]->size.y;
1111
1112 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1113 dst.x = store->sub_targets[i]->size.x + store->sub_targets[i]->size.w;
1114 dst.y = store->sub_targets[i]->size.y;
1115
1116 alphablit(text1, NULL, pwindow->dst->surface, &dst, 255);
1117 i++;
1118 }
1119
1122 }
1124
1126 widget_flush(pwindow);
1127}
1128
1129/**********************************************************************/
1133 struct widget *pwindow,
1134 struct techs_buttons *store)
1135{
1136 struct widget *pwidget;
1137 struct widget *last, *budynki;
1138 struct widget *dock = store->dock;
1140 int start_x, start_y, imp_count, unit_count, flags_count, gov_count;
1141 char buffer[bufsz];
1142 SDL_Surface *surf;
1143
1144 start_x = (pwindow->area.x + adj_size(1) + width + help_dlg->active_widget_list->size.w + adj_size(20));
1145
1146 /* Tech tree icon */
1147 pwidget = create_icon2(current_theme->tech_tree_icon, pwindow->dst,
1149
1150 set_wstate(pwidget, FC_WS_NORMAL);
1152 pwidget->id = MAX_ID - tech;
1153 widget_add_as_prev(pwidget, dock);
1154 dock = pwidget;
1155
1156 /* Tech name (heading) */
1157 pwidget
1159 pwindow->dst,
1162
1163 pwidget->id = ID_LABEL;
1164 widget_add_as_prev(pwidget, dock);
1165 dock = pwidget;
1166
1167 /* Target techs */
1168 targets_count = 0;
1170 if ((targets_count < 6)
1171 && (advance_required(aidx, AR_ONE) == tech
1172 || advance_required(aidx, AR_TWO) == tech)) {
1173 pwidget
1178 pwidget->string_utf8->fgcol = *get_tech_color(aidx);
1179 max_width = MAX(max_width, pwidget->size.w);
1180 set_wstate(pwidget, FC_WS_NORMAL);
1181 pwidget->action = change_tech_callback;
1182 pwidget->id = MAX_ID - aidx;
1183 widget_add_as_prev(pwidget, dock);
1184 dock = pwidget;
1185 store->targets[targets_count++] = pwidget;
1186 }
1188 if (targets_count < 6) {
1189 store->targets[targets_count] = NULL;
1190 }
1191
1193 if (targets_count > 0) {
1194 int sub_tech;
1195
1196 for (i = 0; i < targets_count; i++) {
1197 sub_tech = MAX_ID - store->targets[i]->id;
1198 if (advance_required(sub_tech, AR_ONE) == tech
1201 } else if (advance_required(sub_tech, AR_TWO) == tech
1204 } else {
1205 continue;
1206 }
1207 pwidget
1213 set_wstate(pwidget, FC_WS_NORMAL);
1214 pwidget->action = change_tech_callback;
1215 pwidget->id = MAX_ID - sub_tech;
1216 widget_add_as_prev(pwidget, dock);
1217 dock = pwidget;
1218 store->sub_targets[sub_targets_count++] = pwidget;
1219 }
1220 }
1221 if (sub_targets_count < 6) {
1223 }
1224
1225 /* Fill array with iprvm. icons */
1226 budynki = pwidget;
1227
1228 /* Target governments */
1229 gov_count = 0;
1230 governments_iterate(gov) {
1231 requirement_vector_iterate(&(gov->reqs), preq) {
1232 if (VUT_ADVANCE == preq->source.kind
1233 && advance_number(preq->source.value.advance) == tech) {
1234
1235 pwidget
1237 pwindow->dst,
1241 set_wstate(pwidget, FC_WS_NORMAL);
1242 pwidget->action = change_gov_callback;
1243 pwidget->id = MAX_ID - government_index(gov);
1244 widget_add_as_prev(pwidget, dock);
1245 dock = pwidget;
1246 gov_count++;
1247 }
1250
1251 /* Target improvements */
1252 imp_count = 0;
1253 improvement_iterate(pimprove) {
1254 if (valid_improvement(pimprove)) {
1255 /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs.
1256 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
1257 * definition. */
1258 requirement_vector_iterate(&(pimprove->reqs), preq) {
1259 if (VUT_ADVANCE == preq->source.kind
1260 && advance_number(preq->source.value.advance) == tech) {
1261 surf = get_building_surface(pimprove);
1263 resize_surface_box(surf, adj_size(48), adj_size(48), 1, TRUE,
1264 TRUE),
1265 pwindow->dst,
1269 set_wstate(pwidget, FC_WS_NORMAL);
1270 if (is_wonder(pimprove)) {
1272 }
1273 pwidget->action = change_impr_callback;
1274 pwidget->id = MAX_ID - improvement_number(pimprove);
1275 widget_add_as_prev(pwidget, dock);
1276 dock = pwidget;
1277 imp_count++;
1278 }
1279
1280 break;
1282 }
1284
1285 unit_count = 0;
1290 adj_size(48), adj_size(48), 1, TRUE, TRUE),
1293 set_wstate(pwidget, FC_WS_NORMAL);
1294 pwidget->action = change_unit_callback;
1295 pwidget->id = MAX_ID - utype_number(un);
1296 widget_add_as_prev(pwidget, dock);
1297 dock = pwidget;
1298 unit_count++;
1299 }
1301
1302 buffer[0] = '\0';
1303 if (tech != A_NONE) {
1304 helptext_advance(buffer, sizeof(buffer), client.conn.playing, "", tech);
1305 }
1306 if (buffer[0] != '\0') {
1308
1310 pwidget = create_iconlabel(NULL, pwindow->dst, pstr, 0);
1311 pwidget->id = ID_LABEL;
1312 widget_add_as_prev(pwidget, dock);
1313 flags_count = 1;
1314 } else {
1315 flags_count = 0;
1316 }
1317
1318 last = pwidget;
1319 /* --------------------------------------------- */
1320
1321 /* Tree button */
1322 pwidget = store->dock->prev;
1323 pwidget->size.x = pwindow->area.x + pwindow->area.w - pwidget->size.w - adj_size(17);
1324 pwidget->size.y = pwindow->area.y + adj_size(16);
1325
1326 /* Tech label */
1327 pwidget = pwidget->prev;
1328 pwidget->size.x = start_x;
1329 pwidget->size.y = pwindow->area.y + adj_size(16);
1330 start_y = pwidget->size.y + pwidget->size.h + adj_size(30);
1331
1332 if (targets_count) {
1333 int j = 0;
1334
1335 i = 0;
1336
1337 while (i < 6 && store->targets[i]) {
1338 store->targets[i]->size.x = pwindow->size.x + start_x;
1339 store->targets[i]->size.y = start_y;
1340
1341 if (store->sub_targets[j]) {
1342 int t0 = MAX_ID - store->targets[i]->id;
1343 int t1 = MAX_ID - store->sub_targets[j]->id;
1344
1345 if (advance_required(t0, AR_ONE) == t1
1346 || advance_required(t0, AR_TWO) == t1) {
1347 store->sub_targets[j]->size.x = pwindow->size.x + start_x + max_width + 60;
1348 store->sub_targets[j]->size.y = store->targets[i]->size.y;
1349 j++;
1350 }
1351 }
1352
1353 start_y += store->targets[i]->size.h;
1354 i++;
1355 }
1356
1357 start_y += adj_size(10);
1358 }
1359 pwidget = NULL;
1360
1361 if (gov_count) {
1362 pwidget = budynki->prev;
1363 while (gov_count-- && pwidget) {
1364 pwidget->size.x = pwindow->size.x + start_x;
1365 pwidget->size.y = start_y;
1366 start_y += pwidget->size.h + adj_size(2);
1367 pwidget = pwidget->prev;
1368 }
1369 }
1370
1371 if (imp_count) {
1372 if (!pwidget) {
1373 pwidget = budynki->prev;
1374 }
1375 while (imp_count-- && pwidget) {
1376 pwidget->size.x = pwindow->size.x + start_x;
1377 pwidget->size.y = start_y;
1378 start_y += pwidget->size.h + adj_size(2);
1379 pwidget = pwidget->prev;
1380 }
1381 }
1382
1383 if (unit_count) {
1384 if (!pwidget) {
1385 pwidget = budynki->prev;
1386 }
1387 while (unit_count-- && pwidget) {
1388 pwidget->size.x = pwindow->size.x + start_x;
1389 pwidget->size.y = start_y;
1390 start_y += pwidget->size.h + adj_size(2);
1391 pwidget = pwidget->prev;
1392 }
1393 }
1394
1395 if (flags_count) {
1396 if (!pwidget) {
1397 pwidget = budynki->prev;
1398 }
1399 while (flags_count-- && pwidget) {
1400 pwidget->size.x = pwindow->size.x + start_x;
1401 pwidget->size.y = start_y;
1402 start_y += pwidget->size.h + adj_size(2);
1403 pwidget = pwidget->prev;
1404 }
1405 }
1406
1407 return last;
1408}
1409
1410/**********************************************************************/
1413static void redraw_tech_tree_dlg(void)
1414{
1416 SDL_Color bg_color = {255, 255, 255, 64};
1417 struct widget *pwindow = help_dlg->end_widget_list;
1418 struct widget *sub0, *sub1;
1419 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1420 struct widget *ptech = store->dock->prev;
1421 int i,j, tech, count;
1422 int step;
1423 int mod;
1424 SDL_Rect dst;
1425
1426 /* Redraw Window with exit button */
1427 redraw_group(pwindow->prev, pwindow, FALSE);
1428
1429 dst.x = pwindow->area.x + pwindow->area.w - adj_size(459) - adj_size(7);
1430 dst.y = pwindow->area.y + adj_size(6);
1431 dst.w = pwindow->area.w - (dst.x - pwindow->area.x) - adj_size(10);
1432 dst.h = pwindow->area.h - (dst.y - pwindow->area.y) - adj_size(10);
1433
1434 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1435
1436 create_frame(pwindow->dst->surface,
1437 dst.x, dst.y, dst.w, dst.h,
1439
1440 /* Draw req arrows */
1441 i = 0;
1442 while (i < 4 && store->sub_req[i]) {
1443 i++;
1444 }
1445 count = i;
1446
1447 i = 0;
1448 while (i < 2 && store->requirement_button[i]) {
1449 tech = MAX_ID - store->requirement_button[i]->id;
1450
1451 /* Find sub req's */
1452 if (i) {
1453 sub0 = NULL;
1454 for (j = count - 1; j >= 0; j--) {
1455 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1456 sub0 = store->sub_req[j];
1457 break;
1458 }
1459 }
1460
1461 sub1 = NULL;
1462 for (j = count - 1; j >= 0; j--) {
1463 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1464 sub1 = store->sub_req[j];
1465 break;
1466 }
1467 }
1468 } else {
1469 sub0 = NULL;
1470 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1471 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1472 sub0 = store->sub_req[j];
1473 break;
1474 }
1475 }
1476
1477 sub1 = NULL;
1478 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1479 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1480 sub1 = store->sub_req[j];
1481 break;
1482 }
1483 }
1484 }
1485
1486 /* Draw main Arrow */
1488 store->requirement_button[i]->size.x + store->requirement_button[i]->size.w,
1489 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1490 ptech->size.x,
1491 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1492 line_color);
1493
1494 /* Draw sub req arrows */
1495 if (sub0 || sub1) {
1497 store->requirement_button[i]->size.x - adj_size(10),
1498 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1499 store->requirement_button[i]->size.x ,
1500 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1501 line_color);
1502 }
1503
1504 if (sub0) {
1506 store->requirement_button[i]->size.x - adj_size(10),
1507 sub0->size.y + sub0->size.h / 2,
1508 store->requirement_button[i]->size.x - adj_size(10),
1509 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1510 line_color);
1512 sub0->size.x + sub0->size.w,
1513 sub0->size.y + sub0->size.h / 2,
1514 store->requirement_button[i]->size.x - adj_size(10),
1515 sub0->size.y + sub0->size.h / 2,
1516 line_color);
1517 }
1518
1519 if (sub1) {
1521 store->requirement_button[i]->size.x - adj_size(10),
1522 sub1->size.y + sub1->size.h / 2,
1523 store->requirement_button[i]->size.x - adj_size(10),
1524 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1525 line_color);
1527 sub1->size.x + sub1->size.w,
1528 sub1->size.y + sub1->size.h / 2,
1529 store->requirement_button[i]->size.x - adj_size(10),
1530 sub1->size.y + sub1->size.h / 2,
1531 line_color);
1532 }
1533 i++;
1534 }
1535
1536 i = 0;
1537 while (i < 6 && store->targets[i]) {
1538 i++;
1539 }
1540 count = i;
1541
1542 if (count > 4) {
1543 mod = 3;
1544 } else {
1545 mod = 2;
1546 }
1547
1548 for (i = 0; i < count; i++) {
1549 tech = MAX_ID - store->targets[i]->id;
1550 step = ptech->size.h / (count + 1);
1551
1552 switch ((i % mod)) {
1553 case 2:
1555 break;
1556 case 1:
1558 break;
1559 default:
1561 break;
1562 }
1563
1564 /* Find sub reqs */
1565 if (advance_required(tech, AR_ONE) == MAX_ID - ptech->id) {
1566 sub0 = ptech;
1567 } else {
1568 sub0 = NULL;
1569 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1570 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_ONE)) {
1571 sub0 = store->sub_targets[j];
1572 break;
1573 }
1574 }
1575 }
1576
1577 if (advance_required(tech, AR_TWO) == MAX_ID - ptech->id) {
1578 sub1 = ptech;
1579 } else {
1580 sub1 = NULL;
1581 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1582 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_TWO)) {
1583 sub1 = store->sub_targets[j];
1584 break;
1585 }
1586 }
1587 }
1588
1589 /* Draw sub targets arrows */
1590 if (sub0 || sub1) {
1591 create_line(store->targets[i]->dst->surface,
1592 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1593 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1594 store->targets[i]->size.x ,
1595 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1596 line_color);
1597 }
1598
1599 if (sub0) {
1600 int y;
1601
1602 if (sub0 == ptech) {
1603 y = sub0->size.y + step * (i + 1);
1604 } else {
1605 y = sub0->size.y + sub0->size.h / 2;
1606 }
1607
1608 create_line(store->targets[i]->dst->surface,
1609 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1610 y,
1611 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1612 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1613 line_color);
1614 create_line(store->targets[i]->dst->surface,
1615 sub0->size.x + sub0->size.w,
1616 y,
1617 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1618 y,
1619 line_color);
1620 }
1621
1622 if (sub1) {
1623 int y;
1624
1625 if (sub1 == ptech) {
1626 y = sub1->size.y + step * (i + 1);
1627 } else {
1628 y = sub1->size.y + sub1->size.h / 2;
1629 }
1630
1631 create_line(store->targets[i]->dst->surface,
1632 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1633 y,
1634 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1635 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1636 line_color);
1637 create_line(store->targets[i]->dst->surface,
1638 sub1->size.x + sub1->size.w,
1639 y,
1640 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1641 y,
1642 line_color);
1643 }
1644 }
1645
1646 /* Redraw rest */
1648
1649 widget_flush(pwindow);
1650}
1651
1652/**********************************************************************/
1656{
1658 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1659
1660 if (store->show_full_tree) {
1661 pwidget->theme2 = current_theme->up_icon;
1662 } else {
1663 pwidget->theme2 = current_theme->down_icon;
1664 }
1665 store->show_full_tree = !store->show_full_tree;
1666 popup_tech_info(MAX_ID - store->dock->prev->id);
1667 }
1668
1669 return -1;
1670}
1671
1672/**********************************************************************/
1676 struct widget *pwindow,
1677 struct techs_buttons *store)
1678{
1680 struct widget *pwidget;
1681 struct widget *ptech;
1682 utf8_str *pstr;
1683 SDL_Surface *surf;
1684 struct widget *dock = store->dock;
1685
1687 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1688
1691 pwidget = create_icon2(surf, pwindow->dst,
1693
1694 set_wstate(pwidget, FC_WS_NORMAL);
1696 pwidget->id = MAX_ID - tech;
1697 widget_add_as_prev(pwidget, dock);
1698 ptech = pwidget;
1699 dock = pwidget;
1700
1701 req_count = 0;
1702 for (i = AR_ONE; i <= AR_TWO; i++) {
1705
1706 if (NULL != vap && A_NONE != ar) {
1709 pwidget = create_icon2(surf, pwindow->dst,
1711 set_wstate(pwidget, FC_WS_NORMAL);
1712 pwidget->action = change_tech_callback;
1713 pwidget->id = MAX_ID - ar;
1714 widget_add_as_prev(pwidget, dock);
1715 dock = pwidget;
1716 store->requirement_button[req_count++] = pwidget;
1717 }
1718 }
1719
1720 sub_req_count = 0;
1721
1722 if (store->show_full_tree && req_count > 0) {
1723 int j, sub_tech;
1724
1725 for (j = 0; j < req_count; j++) {
1726 sub_tech = MAX_ID - store->requirement_button[j]->id;
1727 for (i = AR_ONE; i <= AR_TWO; i++) {
1730
1731 if (NULL != vap && A_NONE != ar) {
1734 pwidget = create_icon2(surf, pwindow->dst,
1736 set_wstate(pwidget, FC_WS_NORMAL);
1737 pwidget->action = change_tech_callback;
1738 pwidget->id = MAX_ID - ar;
1739 widget_add_as_prev(pwidget, dock);
1740 dock = pwidget;
1741 store->sub_req[sub_req_count++] = pwidget;
1742 }
1743 }
1744 }
1745 }
1746
1747 if (sub_req_count < 4) {
1748 store->sub_req[sub_req_count] = NULL;
1749 }
1750
1751 targets_count = 0;
1753 if ((targets_count < 6)
1754 && (advance_required(aidx, AR_ONE) == tech
1755 || advance_required(aidx, AR_TWO) == tech)) {
1758 pwidget = create_icon2(surf, pwindow->dst,
1760
1761 set_wstate(pwidget, FC_WS_NORMAL);
1762 pwidget->action = change_tech_callback;
1763 pwidget->id = MAX_ID - aidx;
1764 widget_add_as_prev(pwidget, dock);
1765 dock = pwidget;
1766 store->targets[targets_count++] = pwidget;
1767 }
1769 if (targets_count < 6) {
1770 store->targets[targets_count] = NULL;
1771 }
1772
1774 if (targets_count > 0) {
1775 int sub_tech;
1776
1777 for (i = 0; i < targets_count; i++) {
1778 sub_tech = MAX_ID - store->targets[i]->id;
1779 if (advance_required(sub_tech, AR_ONE) == tech
1782 } else if (advance_required(sub_tech, AR_TWO) == tech
1785 } else {
1786 continue;
1787 }
1788
1791 pwidget = create_icon2(surf, pwindow->dst,
1793 set_wstate(pwidget, FC_WS_NORMAL);
1794 pwidget->action = change_tech_callback;
1795 pwidget->id = MAX_ID - sub_tech;
1796 widget_add_as_prev(pwidget, dock);
1797 dock = pwidget;
1798 store->sub_targets[sub_targets_count++] = pwidget;
1799 }
1800 }
1801 if (sub_targets_count < 6) {
1803 }
1804
1806
1807 /* ------------------------------------------ */
1808 if (sub_req_count > 0) {
1809 w = (adj_size(20) + store->sub_req[0]->size.w) * 2;
1810 w += (pwindow->size.w - (20 + store->sub_req[0]->size.w + w + ptech->size.w)) / 2;
1811 } else {
1812 if (req_count > 0) {
1813 w = (pwindow->area.x + 1
1814 + width + store->requirement_button[0]->size.w * 2 + adj_size(20));
1815 w += (pwindow->size.w - ((adj_size(20) + store->requirement_button[0]->size.w)
1816 + w + ptech->size.w)) / 2;
1817 } else {
1818 w = (pwindow->size.w - ptech->size.w) / 2;
1819 }
1820 }
1821
1822 ptech->size.x = pwindow->size.x + w;
1823 ptech->size.y = pwindow->area.y + (pwindow->area.h - ptech->size.h) / 2;
1824
1825 if (req_count > 0) {
1826 h = (req_count == 1 ? store->requirement_button[0]->size.h :
1827 req_count * (store->requirement_button[0]->size.h + adj_size(80)) - adj_size(80));
1828 h = ptech->size.y + (ptech->size.h - h) / 2;
1829 for (i = 0; i < req_count; i++) {
1830 store->requirement_button[i]->size.x
1831 = ptech->size.x - adj_size(20) - store->requirement_button[i]->size.w;
1832 store->requirement_button[i]->size.y = h;
1833 h += (store->requirement_button[i]->size.h + adj_size(80));
1834 }
1835 }
1836
1837 if (sub_req_count > 0) {
1838 h = (sub_req_count == 1 ? store->sub_req[0]->size.h :
1839 sub_req_count * (store->sub_req[0]->size.h + adj_size(20)) - adj_size(20));
1840 h = ptech->size.y + (ptech->size.h - h) / 2;
1841 for (i = 0; i < sub_req_count; i++) {
1842 store->sub_req[i]->size.x
1843 = ptech->size.x - (adj_size(20) + store->sub_req[i]->size.w) * 2;
1844 store->sub_req[i]->size.y = h;
1845 h += (store->sub_req[i]->size.h + adj_size(20));
1846 }
1847 }
1848
1849 if (targets_count > 0) {
1850 h = (targets_count == 1 ? store->targets[0]->size.h :
1851 targets_count * (store->targets[0]->size.h + adj_size(20)) - adj_size(20));
1852 h = ptech->size.y + (ptech->size.h - h) / 2;
1853 for (i = 0; i < targets_count; i++) {
1854 store->targets[i]->size.x = ptech->size.x + ptech->size.w + adj_size(20);
1855 store->targets[i]->size.y = h;
1856 h += (store->targets[i]->size.h + adj_size(20));
1857 }
1858 }
1859
1860 if (sub_targets_count > 0) {
1861 if (sub_targets_count < 3) {
1862 store->sub_targets[0]->size.x
1863 = ptech->size.x + ptech->size.w - store->sub_targets[0]->size.w;
1864 store->sub_targets[0]->size.y
1865 = ptech->size.y - store->sub_targets[0]->size.h - adj_size(10);
1866 if (store->sub_targets[1]) {
1867 store->sub_targets[1]->size.x
1868 = ptech->size.x + ptech->size.w - store->sub_targets[1]->size.w;
1869 store->sub_targets[1]->size.y = ptech->size.y + ptech->size.h + adj_size(10);
1870 }
1871 } else {
1872 if (sub_targets_count < 5) {
1873 for (i = 0; i < MIN(sub_targets_count, 4); i++) {
1874 store->sub_targets[i]->size.x
1875 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1876 if (i < 2) {
1877 store->sub_targets[i]->size.y
1878 = ptech->size.y - (store->sub_targets[i]->size.h + adj_size(5)) * (2 - i);
1879 } else {
1880 store->sub_targets[i]->size.y
1881 = ptech->size.y + ptech->size.h + adj_size(5)
1882 + (store->sub_targets[i]->size.h + adj_size(5)) * (i - 2);
1883 }
1884 }
1885 } else {
1886 h = (store->sub_targets[0]->size.h + adj_size(6));
1887 for (i = 0; i < MIN(sub_targets_count, 6); i++) {
1888 switch (i) {
1889 case 0:
1890 store->sub_targets[i]->size.x
1891 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1892 store->sub_targets[i]->size.y = ptech->size.y - h * 2;
1893 break;
1894 case 1:
1895 store->sub_targets[i]->size.x
1896 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1897 - adj_size(10);
1898 store->sub_targets[i]->size.y = ptech->size.y - h - h / 2;
1899 break;
1900 case 2:
1901 store->sub_targets[i]->size.x
1902 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1903 store->sub_targets[i]->size.y = ptech->size.y - h;
1904 break;
1905 case 3:
1906 store->sub_targets[i]->size.x
1907 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1908 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6);
1909 break;
1910 case 4:
1911 store->sub_targets[i]->size.x
1912 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1913 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6) + h;
1914 break;
1915 default:
1916 store->sub_targets[i]->size.x
1917 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1918 - adj_size(10);
1919 store->sub_targets[i]->size.y
1920 = ptech->size.y + ptech->size.h + adj_size(6) + h / 2 ;
1921 break;
1922 }
1923 }
1924 }
1925 }
1926 }
1927
1928 return pwidget;
1929}
1930
1931/**********************************************************************/
1935{
1936 struct widget *pwindow;
1937 struct techs_buttons *store;
1938 struct widget *close_button = NULL;
1939 struct widget *advance_label = NULL;
1940 struct widget *list_toggle_button = NULL;
1941 struct widget *dock;
1942 utf8_str *title;
1943 utf8_str *pstr;
1944 SDL_Surface *surf;
1945 int h, tech_count;
1946 bool created;
1947 int scrollbar_width = 0;
1948 SDL_Rect area;
1949
1950 if (current_help_dlg != HELP_TECH) {
1952 }
1953
1954 /* Create new dialog if it doesn't exist yet */
1955 if (!help_dlg) {
1957 created = TRUE;
1958
1959 /* Create dialog */
1960 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
1961 store = fc_calloc(1, sizeof(struct techs_buttons));
1962
1963 store->show_tree = FALSE;
1964 store->show_full_tree = FALSE;
1965
1966 /* Create window */
1967 title = create_utf8_from_char_fonto(_("Help : Advances Tree"),
1969 title->style |= TTF_STYLE_BOLD;
1970
1972 pwindow->data.ptr = (void *)store;
1974 set_wstate(pwindow, FC_WS_NORMAL);
1975
1976 add_to_gui_list(ID_WINDOW, pwindow);
1977
1978 help_dlg->end_widget_list = pwindow;
1979
1980 /* ------------------ */
1981
1982 /* Close button */
1983 close_button = create_themeicon(current_theme->small_cancel_icon, pwindow->dst,
1986 close_button->info_label
1987 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
1988 close_button->action = exit_help_dlg_callback;
1989 set_wstate(close_button, FC_WS_NORMAL);
1990 close_button->key = SDLK_ESCAPE;
1991
1992 add_to_gui_list(ID_BUTTON, close_button);
1993
1994 /* ------------------ */
1995 dock = close_button;
1996
1997 /* --- Create scrollable advance list on the left side ---*/
1999 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
2000
2001 tech_count = 0;
2004
2005 if (vap) {
2008 advance_label = create_icon2(surf, pwindow->dst,
2010
2014
2015 if (tech_count++ >= 10) {
2017 }
2018 }
2020
2022
2026
2027 if (tech_count > 10) {
2030 }
2031
2032 /* Toggle techs list button */
2034 current_theme->up_icon,
2035 pwindow->dst,
2036 _("Advances"),
2037 FONTO_DEFAULT, 0);
2039 if (store->show_tree) {
2041 }
2044
2046
2047 dock = list_toggle_button;
2048 store->dock = dock;
2049 } else {
2050 created = FALSE;
2052 pwindow = help_dlg->end_widget_list;
2053 store = (struct techs_buttons *)pwindow->data.ptr;
2054 dock = store->dock;
2055
2056 /* Delete any previous list entries */
2060 }
2061
2062 /* Show/hide techs list */
2064
2065 if (store->show_tree) {
2067 } else {
2069 }
2070
2071 if (store->show_full_tree) {
2072 /* All entries are visible without scrolling */
2076 } else {
2077 int count = help_dlg->scroll->active;
2078
2080 while (advance_label->prev != NULL && --count > 0) {
2082 }
2085 }
2086 }
2087
2088 /* --------------------------------------------------------- */
2089 if (created) {
2090
2092 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
2093 FREESURFACE(surf);
2094 }
2095
2096 area = pwindow->area;
2097
2098 widget_set_position(pwindow,
2099 (main_window_width() - pwindow->size.w) / 2,
2100 (main_window_height() - pwindow->size.h) / 2);
2101
2102 /* Exit button */
2103 close_button = pwindow->prev;
2104 widget_set_position(close_button,
2105 area.x + area.w - close_button->size.w - 1,
2106 pwindow->size.y + adj_size(2));
2107
2108 /* List toggle button */
2109 list_toggle_button = store->dock;
2110 widget_set_position(list_toggle_button, area.x, area.y);
2111
2112 /* List entries */
2114 area.y + list_toggle_button->size.h, 0, 0,
2117 /* Scrollbar */
2118 if (help_dlg->scroll) {
2120 area.x, area.y + list_toggle_button->size.h,
2121 h, FALSE);
2122 }
2123 }
2124
2125 if (store->show_tree) {
2128 } else {
2131 }
2132}
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:663
struct civclient client
char * incite_cost
Definition comments.c:75
QString current_theme
Definition fc_client.cpp:65
int Tech_type_id
Definition fc_types.h:377
int Impr_type_id
Definition fc_types.h:376
int Unit_type_id
Definition fc_types.h:382
@ 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:124
#define governments_iterate_end
Definition government.h:127
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:1936
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:1042
enum help_page_type current_help_dlg
Definition helpdlg.c:68
static void redraw_tech_info_dlg(void)
Definition helpdlg.c:1061
static void redraw_unit_info_dlg(void)
Definition helpdlg.c:604
static int change_tech_callback(struct widget *pwidget)
Definition helpdlg.c:1030
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:1134
void popup_impr_info(Impr_type_id impr)
Definition helpdlg.c:202
static void redraw_tech_tree_dlg(void)
Definition helpdlg.c:1415
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:1657
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:3299
char * helptext_unit(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct unit_type *utype, bool class_help)
Definition helpdata.c:1932
char * helptext_building(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct impr_type *pimprove)
Definition helpdata.c:1381
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:82
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
union widget::@194 data
SDL_Keycode key
Definition widget.h:153
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:2724
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:2710
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:855
#define unit_type_iterate_end
Definition unittype.h:862
#define U_NOT_OBSOLETED
Definition unittype.h:528