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 if (buffer[0] != '\0') {
934
939 text = TRUE;
940 }
941
943
944 /* --------------------------------------------------------- */
945 if (created) {
946
948 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
949 FREESURFACE(surf);
950 }
951
952 area = pwindow->area;
953
954 widget_set_position(pwindow,
955 (main_window_width() - pwindow->size.w) / 2,
956 (main_window_height() - pwindow->size.h) / 2);
957
958 /* Exit button */
959 close_button = pwindow->prev;
960 widget_set_position(close_button,
961 area.x + area.w - close_button->size.w - 1,
962 pwindow->size.y + adj_size(2));
963
964 /* List toggle button */
965 list_toggle_button = store->dock;
967
968 /* List entries */
970 area.y + list_toggle_button->size.h, 0, 0,
973
974 /* Scrollbar */
975 if (help_dlg->scroll) {
977 area.x, area.y + list_toggle_button->size.h,
978 h, FALSE);
979 }
980 }
981
982 unit_name_label = store->dock->prev;
983 widget_set_position(unit_name_label, start_x, area.y + adj_size(16));
984
985 start_y = unit_name_label->size.y + unit_name_label->size.h + adj_size(10);
986
989
990 start_y += unit_info_label->size.h;
991
994
997 requirement_label->size.x + requirement_label->size.w + adj_size(5),
998 start_y);
999
1002 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
1003 start_y);
1004
1007 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
1008 start_y);
1009
1010 start_y += obsolete_by_label2->size.h + adj_size(20);
1011
1012 if (text) {
1015 }
1016
1018}
1019
1020/* =============================================== */
1021/* ==================== Tech Tree ================ */
1022/* =============================================== */
1023
1024/**********************************************************************/
1027static int change_tech_callback(struct widget *pwidget)
1028{
1030 popup_tech_info(MAX_ID - pwidget->id);
1031 }
1032
1033 return -1;
1034}
1035
1036/**********************************************************************/
1039static int show_tech_tree_callback(struct widget *pwidget)
1040{
1042 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1043
1044 store->show_tree = !store->show_tree;
1045 if (!store->show_tree) {
1046 store->show_full_tree = FALSE;
1047 store->dock->theme2 = current_theme->up_icon;
1048 }
1049 popup_tech_info(MAX_ID - store->dock->prev->id);
1050 }
1051
1052 return -1;
1053}
1054
1055/**********************************************************************/
1058static void redraw_tech_info_dlg(void)
1059{
1060 SDL_Color bg_color = {255, 255, 255, 64};
1061 struct widget *pwindow = help_dlg->end_widget_list;
1062 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1064 utf8_str *pstr;
1065 SDL_Rect dst;
1066
1067 redraw_group(pwindow->prev, pwindow, FALSE);
1068
1069 dst.x = store->dock->prev->prev->size.x - adj_size(10);
1070 dst.y = store->dock->prev->prev->size.y - adj_size(10);
1071 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
1072 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
1073
1074 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1075
1076 create_frame(pwindow->dst->surface,
1077 dst.x, dst.y, dst.w, dst.h,
1079
1080 /* -------------------------- */
1082 pstr->style |= TTF_STYLE_BOLD;
1083
1085 dst.x = store->dock->prev->prev->size.x;
1086 if (store->targets[0]) {
1087 dst.y = store->targets[0]->size.y - text0->h;
1088 } else {
1089 dst.y = store->dock->prev->prev->size.y
1090 + store->dock->prev->prev->size.h + adj_size(10);
1091 }
1092
1093 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1095
1096 if (store->sub_targets[0]) {
1097 int i;
1098
1100
1101 copy_chars_to_utf8_str(pstr, _("( with "));
1103
1106 i = 0;
1108 dst.x = store->sub_targets[i]->size.x - text0->w;
1109 dst.y = store->sub_targets[i]->size.y;
1110
1111 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1112 dst.x = store->sub_targets[i]->size.x + store->sub_targets[i]->size.w;
1113 dst.y = store->sub_targets[i]->size.y;
1114
1115 alphablit(text1, NULL, pwindow->dst->surface, &dst, 255);
1116 i++;
1117 }
1118
1121 }
1123
1125 widget_flush(pwindow);
1126}
1127
1128/**********************************************************************/
1132 struct widget *pwindow,
1133 struct techs_buttons *store)
1134{
1135 struct widget *pwidget;
1136 struct widget *last, *budynki;
1137 struct widget *dock = store->dock;
1139 int start_x, start_y, imp_count, unit_count, flags_count, gov_count;
1140 char buffer[bufsz];
1141 SDL_Surface *surf;
1142
1143 start_x = (pwindow->area.x + adj_size(1) + width + help_dlg->active_widget_list->size.w + adj_size(20));
1144
1145 /* Tech tree icon */
1146 pwidget = create_icon2(current_theme->tech_tree_icon, pwindow->dst,
1148
1149 set_wstate(pwidget, FC_WS_NORMAL);
1151 pwidget->id = MAX_ID - tech;
1152 widget_add_as_prev(pwidget, dock);
1153 dock = pwidget;
1154
1155 /* Tech name (heading) */
1156 pwidget
1158 pwindow->dst,
1161
1162 pwidget->id = ID_LABEL;
1163 widget_add_as_prev(pwidget, dock);
1164 dock = pwidget;
1165
1166 /* Target techs */
1167 targets_count = 0;
1169 if ((targets_count < 6)
1170 && (advance_required(aidx, AR_ONE) == tech
1171 || advance_required(aidx, AR_TWO) == tech)) {
1172 pwidget
1177 pwidget->string_utf8->fgcol = *get_tech_color(aidx);
1178 max_width = MAX(max_width, pwidget->size.w);
1179 set_wstate(pwidget, FC_WS_NORMAL);
1180 pwidget->action = change_tech_callback;
1181 pwidget->id = MAX_ID - aidx;
1182 widget_add_as_prev(pwidget, dock);
1183 dock = pwidget;
1184 store->targets[targets_count++] = pwidget;
1185 }
1187 if (targets_count < 6) {
1188 store->targets[targets_count] = NULL;
1189 }
1190
1192 if (targets_count > 0) {
1193 int sub_tech;
1194
1195 for (i = 0; i < targets_count; i++) {
1196 sub_tech = MAX_ID - store->targets[i]->id;
1197 if (advance_required(sub_tech, AR_ONE) == tech
1200 } else if (advance_required(sub_tech, AR_TWO) == tech
1203 } else {
1204 continue;
1205 }
1206 pwidget
1212 set_wstate(pwidget, FC_WS_NORMAL);
1213 pwidget->action = change_tech_callback;
1214 pwidget->id = MAX_ID - sub_tech;
1215 widget_add_as_prev(pwidget, dock);
1216 dock = pwidget;
1217 store->sub_targets[sub_targets_count++] = pwidget;
1218 }
1219 }
1220 if (sub_targets_count < 6) {
1222 }
1223
1224 /* Fill array with iprvm. icons */
1225 budynki = pwidget;
1226
1227 /* Target governments */
1228 gov_count = 0;
1229 governments_iterate(gov) {
1230 requirement_vector_iterate(&(gov->reqs), preq) {
1231 if (VUT_ADVANCE == preq->source.kind
1232 && advance_number(preq->source.value.advance) == tech) {
1233
1234 pwidget
1236 pwindow->dst,
1240 set_wstate(pwidget, FC_WS_NORMAL);
1241 pwidget->action = change_gov_callback;
1242 pwidget->id = MAX_ID - government_index(gov);
1243 widget_add_as_prev(pwidget, dock);
1244 dock = pwidget;
1245 gov_count++;
1246 }
1249
1250 /* Target improvements */
1251 imp_count = 0;
1252 improvement_iterate(pimprove) {
1253 if (valid_improvement(pimprove)) {
1254 /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs.
1255 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
1256 * definition. */
1257 requirement_vector_iterate(&(pimprove->reqs), preq) {
1258 if (VUT_ADVANCE == preq->source.kind
1259 && advance_number(preq->source.value.advance) == tech) {
1260 surf = get_building_surface(pimprove);
1262 resize_surface_box(surf, adj_size(48), adj_size(48), 1, TRUE,
1263 TRUE),
1264 pwindow->dst,
1268 set_wstate(pwidget, FC_WS_NORMAL);
1269 if (is_wonder(pimprove)) {
1271 }
1272 pwidget->action = change_impr_callback;
1273 pwidget->id = MAX_ID - improvement_number(pimprove);
1274 widget_add_as_prev(pwidget, dock);
1275 dock = pwidget;
1276 imp_count++;
1277 }
1278
1279 break;
1281 }
1283
1284 unit_count = 0;
1289 adj_size(48), adj_size(48), 1, TRUE, TRUE),
1292 set_wstate(pwidget, FC_WS_NORMAL);
1293 pwidget->action = change_unit_callback;
1294 pwidget->id = MAX_ID - utype_number(un);
1295 widget_add_as_prev(pwidget, dock);
1296 dock = pwidget;
1297 unit_count++;
1298 }
1300
1301 buffer[0] = '\0';
1302 if (tech != A_NONE) {
1303 helptext_advance(buffer, sizeof(buffer), client.conn.playing, "", tech);
1304 }
1305 if (buffer[0] != '\0') {
1307
1309 pwidget = create_iconlabel(NULL, pwindow->dst, pstr, 0);
1310 pwidget->id = ID_LABEL;
1311 widget_add_as_prev(pwidget, dock);
1312 flags_count = 1;
1313 } else {
1314 flags_count = 0;
1315 }
1316
1317 last = pwidget;
1318 /* --------------------------------------------- */
1319
1320 /* Tree button */
1321 pwidget = store->dock->prev;
1322 pwidget->size.x = pwindow->area.x + pwindow->area.w - pwidget->size.w - adj_size(17);
1323 pwidget->size.y = pwindow->area.y + adj_size(16);
1324
1325 /* Tech label */
1326 pwidget = pwidget->prev;
1327 pwidget->size.x = start_x;
1328 pwidget->size.y = pwindow->area.y + adj_size(16);
1329 start_y = pwidget->size.y + pwidget->size.h + adj_size(30);
1330
1331 if (targets_count) {
1332 int j = 0;
1333
1334 i = 0;
1335
1336 while (i < 6 && store->targets[i]) {
1337 store->targets[i]->size.x = pwindow->size.x + start_x;
1338 store->targets[i]->size.y = start_y;
1339
1340 if (store->sub_targets[j]) {
1341 int t0 = MAX_ID - store->targets[i]->id;
1342 int t1 = MAX_ID - store->sub_targets[j]->id;
1343
1344 if (advance_required(t0, AR_ONE) == t1
1345 || advance_required(t0, AR_TWO) == t1) {
1346 store->sub_targets[j]->size.x = pwindow->size.x + start_x + max_width + 60;
1347 store->sub_targets[j]->size.y = store->targets[i]->size.y;
1348 j++;
1349 }
1350 }
1351
1352 start_y += store->targets[i]->size.h;
1353 i++;
1354 }
1355
1356 start_y += adj_size(10);
1357 }
1358 pwidget = NULL;
1359
1360 if (gov_count) {
1361 pwidget = budynki->prev;
1362 while (gov_count-- && pwidget) {
1363 pwidget->size.x = pwindow->size.x + start_x;
1364 pwidget->size.y = start_y;
1365 start_y += pwidget->size.h + adj_size(2);
1366 pwidget = pwidget->prev;
1367 }
1368 }
1369
1370 if (imp_count) {
1371 if (!pwidget) {
1372 pwidget = budynki->prev;
1373 }
1374 while (imp_count-- && pwidget) {
1375 pwidget->size.x = pwindow->size.x + start_x;
1376 pwidget->size.y = start_y;
1377 start_y += pwidget->size.h + adj_size(2);
1378 pwidget = pwidget->prev;
1379 }
1380 }
1381
1382 if (unit_count) {
1383 if (!pwidget) {
1384 pwidget = budynki->prev;
1385 }
1386 while (unit_count-- && pwidget) {
1387 pwidget->size.x = pwindow->size.x + start_x;
1388 pwidget->size.y = start_y;
1389 start_y += pwidget->size.h + adj_size(2);
1390 pwidget = pwidget->prev;
1391 }
1392 }
1393
1394 if (flags_count) {
1395 if (!pwidget) {
1396 pwidget = budynki->prev;
1397 }
1398 while (flags_count-- && pwidget) {
1399 pwidget->size.x = pwindow->size.x + start_x;
1400 pwidget->size.y = start_y;
1401 start_y += pwidget->size.h + adj_size(2);
1402 pwidget = pwidget->prev;
1403 }
1404 }
1405
1406 return last;
1407}
1408
1409/**********************************************************************/
1412static void redraw_tech_tree_dlg(void)
1413{
1415 SDL_Color bg_color = {255, 255, 255, 64};
1416 struct widget *pwindow = help_dlg->end_widget_list;
1417 struct widget *sub0, *sub1;
1418 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1419 struct widget *ptech = store->dock->prev;
1420 int i,j, tech, count;
1421 int step;
1422 int mod;
1423 SDL_Rect dst;
1424
1425 /* Redraw Window with exit button */
1426 redraw_group(pwindow->prev, pwindow, FALSE);
1427
1428 dst.x = pwindow->area.x + pwindow->area.w - adj_size(459) - adj_size(7);
1429 dst.y = pwindow->area.y + adj_size(6);
1430 dst.w = pwindow->area.w - (dst.x - pwindow->area.x) - adj_size(10);
1431 dst.h = pwindow->area.h - (dst.y - pwindow->area.y) - adj_size(10);
1432
1433 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1434
1435 create_frame(pwindow->dst->surface,
1436 dst.x, dst.y, dst.w, dst.h,
1438
1439 /* Draw req arrows */
1440 i = 0;
1441 while (i < 4 && store->sub_req[i]) {
1442 i++;
1443 }
1444 count = i;
1445
1446 i = 0;
1447 while (i < 2 && store->requirement_button[i]) {
1448 tech = MAX_ID - store->requirement_button[i]->id;
1449
1450 /* Find sub req's */
1451 if (i) {
1452 sub0 = NULL;
1453 for (j = count - 1; j >= 0; j--) {
1454 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1455 sub0 = store->sub_req[j];
1456 break;
1457 }
1458 }
1459
1460 sub1 = NULL;
1461 for (j = count - 1; j >= 0; j--) {
1462 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1463 sub1 = store->sub_req[j];
1464 break;
1465 }
1466 }
1467 } else {
1468 sub0 = NULL;
1469 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1470 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1471 sub0 = store->sub_req[j];
1472 break;
1473 }
1474 }
1475
1476 sub1 = NULL;
1477 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1478 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1479 sub1 = store->sub_req[j];
1480 break;
1481 }
1482 }
1483 }
1484
1485 /* Draw main Arrow */
1487 store->requirement_button[i]->size.x + store->requirement_button[i]->size.w,
1488 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1489 ptech->size.x,
1490 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1491 line_color);
1492
1493 /* Draw sub req arrows */
1494 if (sub0 || sub1) {
1496 store->requirement_button[i]->size.x - adj_size(10),
1497 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1498 store->requirement_button[i]->size.x ,
1499 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1500 line_color);
1501 }
1502
1503 if (sub0) {
1505 store->requirement_button[i]->size.x - adj_size(10),
1506 sub0->size.y + sub0->size.h / 2,
1507 store->requirement_button[i]->size.x - adj_size(10),
1508 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1509 line_color);
1511 sub0->size.x + sub0->size.w,
1512 sub0->size.y + sub0->size.h / 2,
1513 store->requirement_button[i]->size.x - adj_size(10),
1514 sub0->size.y + sub0->size.h / 2,
1515 line_color);
1516 }
1517
1518 if (sub1) {
1520 store->requirement_button[i]->size.x - adj_size(10),
1521 sub1->size.y + sub1->size.h / 2,
1522 store->requirement_button[i]->size.x - adj_size(10),
1523 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1524 line_color);
1526 sub1->size.x + sub1->size.w,
1527 sub1->size.y + sub1->size.h / 2,
1528 store->requirement_button[i]->size.x - adj_size(10),
1529 sub1->size.y + sub1->size.h / 2,
1530 line_color);
1531 }
1532 i++;
1533 }
1534
1535 i = 0;
1536 while (i < 6 && store->targets[i]) {
1537 i++;
1538 }
1539 count = i;
1540
1541 if (count > 4) {
1542 mod = 3;
1543 } else {
1544 mod = 2;
1545 }
1546
1547 for (i = 0; i < count; i++) {
1548 tech = MAX_ID - store->targets[i]->id;
1549 step = ptech->size.h / (count + 1);
1550
1551 switch ((i % mod)) {
1552 case 2:
1554 break;
1555 case 1:
1557 break;
1558 default:
1560 break;
1561 }
1562
1563 /* Find sub reqs */
1564 if (advance_required(tech, AR_ONE) == MAX_ID - ptech->id) {
1565 sub0 = ptech;
1566 } else {
1567 sub0 = NULL;
1568 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1569 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_ONE)) {
1570 sub0 = store->sub_targets[j];
1571 break;
1572 }
1573 }
1574 }
1575
1576 if (advance_required(tech, AR_TWO) == MAX_ID - ptech->id) {
1577 sub1 = ptech;
1578 } else {
1579 sub1 = NULL;
1580 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1581 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_TWO)) {
1582 sub1 = store->sub_targets[j];
1583 break;
1584 }
1585 }
1586 }
1587
1588 /* Draw sub targets arrows */
1589 if (sub0 || sub1) {
1590 create_line(store->targets[i]->dst->surface,
1591 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1592 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1593 store->targets[i]->size.x ,
1594 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1595 line_color);
1596 }
1597
1598 if (sub0) {
1599 int y;
1600
1601 if (sub0 == ptech) {
1602 y = sub0->size.y + step * (i + 1);
1603 } else {
1604 y = sub0->size.y + sub0->size.h / 2;
1605 }
1606
1607 create_line(store->targets[i]->dst->surface,
1608 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1609 y,
1610 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1611 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1612 line_color);
1613 create_line(store->targets[i]->dst->surface,
1614 sub0->size.x + sub0->size.w,
1615 y,
1616 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1617 y,
1618 line_color);
1619 }
1620
1621 if (sub1) {
1622 int y;
1623
1624 if (sub1 == ptech) {
1625 y = sub1->size.y + step * (i + 1);
1626 } else {
1627 y = sub1->size.y + sub1->size.h / 2;
1628 }
1629
1630 create_line(store->targets[i]->dst->surface,
1631 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1632 y,
1633 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1634 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1635 line_color);
1636 create_line(store->targets[i]->dst->surface,
1637 sub1->size.x + sub1->size.w,
1638 y,
1639 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1640 y,
1641 line_color);
1642 }
1643 }
1644
1645 /* Redraw rest */
1647
1648 widget_flush(pwindow);
1649}
1650
1651/**********************************************************************/
1655{
1657 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1658
1659 if (store->show_full_tree) {
1660 pwidget->theme2 = current_theme->up_icon;
1661 } else {
1662 pwidget->theme2 = current_theme->down_icon;
1663 }
1664 store->show_full_tree = !store->show_full_tree;
1665 popup_tech_info(MAX_ID - store->dock->prev->id);
1666 }
1667
1668 return -1;
1669}
1670
1671/**********************************************************************/
1675 struct widget *pwindow,
1676 struct techs_buttons *store)
1677{
1679 struct widget *pwidget;
1680 struct widget *ptech;
1681 utf8_str *pstr;
1682 SDL_Surface *surf;
1683 struct widget *dock = store->dock;
1684
1686 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1687
1690 pwidget = create_icon2(surf, pwindow->dst,
1692
1693 set_wstate(pwidget, FC_WS_NORMAL);
1695 pwidget->id = MAX_ID - tech;
1696 widget_add_as_prev(pwidget, dock);
1697 ptech = pwidget;
1698 dock = pwidget;
1699
1700 req_count = 0;
1701 for (i = AR_ONE; i <= AR_TWO; i++) {
1704
1705 if (NULL != vap && A_NONE != ar) {
1708 pwidget = create_icon2(surf, pwindow->dst,
1710 set_wstate(pwidget, FC_WS_NORMAL);
1711 pwidget->action = change_tech_callback;
1712 pwidget->id = MAX_ID - ar;
1713 widget_add_as_prev(pwidget, dock);
1714 dock = pwidget;
1715 store->requirement_button[req_count++] = pwidget;
1716 }
1717 }
1718
1719 sub_req_count = 0;
1720
1721 if (store->show_full_tree && req_count > 0) {
1722 int j, sub_tech;
1723
1724 for (j = 0; j < req_count; j++) {
1725 sub_tech = MAX_ID - store->requirement_button[j]->id;
1726 for (i = AR_ONE; i <= AR_TWO; i++) {
1729
1730 if (NULL != vap && A_NONE != ar) {
1733 pwidget = create_icon2(surf, pwindow->dst,
1735 set_wstate(pwidget, FC_WS_NORMAL);
1736 pwidget->action = change_tech_callback;
1737 pwidget->id = MAX_ID - ar;
1738 widget_add_as_prev(pwidget, dock);
1739 dock = pwidget;
1740 store->sub_req[sub_req_count++] = pwidget;
1741 }
1742 }
1743 }
1744 }
1745
1746 if (sub_req_count < 4) {
1747 store->sub_req[sub_req_count] = NULL;
1748 }
1749
1750 targets_count = 0;
1752 if ((targets_count < 6)
1753 && (advance_required(aidx, AR_ONE) == tech
1754 || advance_required(aidx, AR_TWO) == tech)) {
1757 pwidget = create_icon2(surf, pwindow->dst,
1759
1760 set_wstate(pwidget, FC_WS_NORMAL);
1761 pwidget->action = change_tech_callback;
1762 pwidget->id = MAX_ID - aidx;
1763 widget_add_as_prev(pwidget, dock);
1764 dock = pwidget;
1765 store->targets[targets_count++] = pwidget;
1766 }
1768 if (targets_count < 6) {
1769 store->targets[targets_count] = NULL;
1770 }
1771
1773 if (targets_count > 0) {
1774 int sub_tech;
1775
1776 for (i = 0; i < targets_count; i++) {
1777 sub_tech = MAX_ID - store->targets[i]->id;
1778 if (advance_required(sub_tech, AR_ONE) == tech
1781 } else if (advance_required(sub_tech, AR_TWO) == tech
1784 } else {
1785 continue;
1786 }
1787
1790 pwidget = create_icon2(surf, pwindow->dst,
1792 set_wstate(pwidget, FC_WS_NORMAL);
1793 pwidget->action = change_tech_callback;
1794 pwidget->id = MAX_ID - sub_tech;
1795 widget_add_as_prev(pwidget, dock);
1796 dock = pwidget;
1797 store->sub_targets[sub_targets_count++] = pwidget;
1798 }
1799 }
1800 if (sub_targets_count < 6) {
1802 }
1803
1805
1806 /* ------------------------------------------ */
1807 if (sub_req_count > 0) {
1808 w = (adj_size(20) + store->sub_req[0]->size.w) * 2;
1809 w += (pwindow->size.w - (20 + store->sub_req[0]->size.w + w + ptech->size.w)) / 2;
1810 } else {
1811 if (req_count > 0) {
1812 w = (pwindow->area.x + 1
1813 + width + store->requirement_button[0]->size.w * 2 + adj_size(20));
1814 w += (pwindow->size.w - ((adj_size(20) + store->requirement_button[0]->size.w)
1815 + w + ptech->size.w)) / 2;
1816 } else {
1817 w = (pwindow->size.w - ptech->size.w) / 2;
1818 }
1819 }
1820
1821 ptech->size.x = pwindow->size.x + w;
1822 ptech->size.y = pwindow->area.y + (pwindow->area.h - ptech->size.h) / 2;
1823
1824 if (req_count > 0) {
1825 h = (req_count == 1 ? store->requirement_button[0]->size.h :
1826 req_count * (store->requirement_button[0]->size.h + adj_size(80)) - adj_size(80));
1827 h = ptech->size.y + (ptech->size.h - h) / 2;
1828 for (i = 0; i < req_count; i++) {
1829 store->requirement_button[i]->size.x
1830 = ptech->size.x - adj_size(20) - store->requirement_button[i]->size.w;
1831 store->requirement_button[i]->size.y = h;
1832 h += (store->requirement_button[i]->size.h + adj_size(80));
1833 }
1834 }
1835
1836 if (sub_req_count > 0) {
1837 h = (sub_req_count == 1 ? store->sub_req[0]->size.h :
1838 sub_req_count * (store->sub_req[0]->size.h + adj_size(20)) - adj_size(20));
1839 h = ptech->size.y + (ptech->size.h - h) / 2;
1840 for (i = 0; i < sub_req_count; i++) {
1841 store->sub_req[i]->size.x
1842 = ptech->size.x - (adj_size(20) + store->sub_req[i]->size.w) * 2;
1843 store->sub_req[i]->size.y = h;
1844 h += (store->sub_req[i]->size.h + adj_size(20));
1845 }
1846 }
1847
1848 if (targets_count > 0) {
1849 h = (targets_count == 1 ? store->targets[0]->size.h :
1850 targets_count * (store->targets[0]->size.h + adj_size(20)) - adj_size(20));
1851 h = ptech->size.y + (ptech->size.h - h) / 2;
1852 for (i = 0; i < targets_count; i++) {
1853 store->targets[i]->size.x = ptech->size.x + ptech->size.w + adj_size(20);
1854 store->targets[i]->size.y = h;
1855 h += (store->targets[i]->size.h + adj_size(20));
1856 }
1857 }
1858
1859 if (sub_targets_count > 0) {
1860 if (sub_targets_count < 3) {
1861 store->sub_targets[0]->size.x
1862 = ptech->size.x + ptech->size.w - store->sub_targets[0]->size.w;
1863 store->sub_targets[0]->size.y
1864 = ptech->size.y - store->sub_targets[0]->size.h - adj_size(10);
1865 if (store->sub_targets[1]) {
1866 store->sub_targets[1]->size.x
1867 = ptech->size.x + ptech->size.w - store->sub_targets[1]->size.w;
1868 store->sub_targets[1]->size.y = ptech->size.y + ptech->size.h + adj_size(10);
1869 }
1870 } else {
1871 if (sub_targets_count < 5) {
1872 for (i = 0; i < MIN(sub_targets_count, 4); i++) {
1873 store->sub_targets[i]->size.x
1874 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1875 if (i < 2) {
1876 store->sub_targets[i]->size.y
1877 = ptech->size.y - (store->sub_targets[i]->size.h + adj_size(5)) * (2 - i);
1878 } else {
1879 store->sub_targets[i]->size.y
1880 = ptech->size.y + ptech->size.h + adj_size(5)
1881 + (store->sub_targets[i]->size.h + adj_size(5)) * (i - 2);
1882 }
1883 }
1884 } else {
1885 h = (store->sub_targets[0]->size.h + adj_size(6));
1886 for (i = 0; i < MIN(sub_targets_count, 6); i++) {
1887 switch (i) {
1888 case 0:
1889 store->sub_targets[i]->size.x
1890 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1891 store->sub_targets[i]->size.y = ptech->size.y - h * 2;
1892 break;
1893 case 1:
1894 store->sub_targets[i]->size.x
1895 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1896 - adj_size(10);
1897 store->sub_targets[i]->size.y = ptech->size.y - h - h / 2;
1898 break;
1899 case 2:
1900 store->sub_targets[i]->size.x
1901 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1902 store->sub_targets[i]->size.y = ptech->size.y - h;
1903 break;
1904 case 3:
1905 store->sub_targets[i]->size.x
1906 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1907 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6);
1908 break;
1909 case 4:
1910 store->sub_targets[i]->size.x
1911 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1912 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6) + h;
1913 break;
1914 default:
1915 store->sub_targets[i]->size.x
1916 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1917 - adj_size(10);
1918 store->sub_targets[i]->size.y
1919 = ptech->size.y + ptech->size.h + adj_size(6) + h / 2 ;
1920 break;
1921 }
1922 }
1923 }
1924 }
1925 }
1926
1927 return pwidget;
1928}
1929
1930/**********************************************************************/
1934{
1935 struct widget *pwindow;
1936 struct techs_buttons *store;
1937 struct widget *close_button = NULL;
1938 struct widget *advance_label = NULL;
1939 struct widget *list_toggle_button = NULL;
1940 struct widget *dock;
1941 utf8_str *title;
1942 utf8_str *pstr;
1943 SDL_Surface *surf;
1944 int h, tech_count;
1945 bool created;
1946 int scrollbar_width = 0;
1947 SDL_Rect area;
1948
1949 if (current_help_dlg != HELP_TECH) {
1951 }
1952
1953 /* Create new dialog if it doesn't exist yet */
1954 if (!help_dlg) {
1956 created = TRUE;
1957
1958 /* Create dialog */
1959 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
1960 store = fc_calloc(1, sizeof(struct techs_buttons));
1961
1962 store->show_tree = FALSE;
1963 store->show_full_tree = FALSE;
1964
1965 /* Create window */
1966 title = create_utf8_from_char_fonto(_("Help : Advances Tree"),
1968 title->style |= TTF_STYLE_BOLD;
1969
1971 pwindow->data.ptr = (void *)store;
1973 set_wstate(pwindow, FC_WS_NORMAL);
1974
1975 add_to_gui_list(ID_WINDOW, pwindow);
1976
1977 help_dlg->end_widget_list = pwindow;
1978
1979 /* ------------------ */
1980
1981 /* Close button */
1982 close_button = create_themeicon(current_theme->small_cancel_icon, pwindow->dst,
1985 close_button->info_label
1986 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
1987 close_button->action = exit_help_dlg_callback;
1988 set_wstate(close_button, FC_WS_NORMAL);
1989 close_button->key = SDLK_ESCAPE;
1990
1991 add_to_gui_list(ID_BUTTON, close_button);
1992
1993 /* ------------------ */
1994 dock = close_button;
1995
1996 /* --- Create scrollable advance list on the left side ---*/
1998 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1999
2000 tech_count = 0;
2003
2004 if (vap) {
2007 advance_label = create_icon2(surf, pwindow->dst,
2009
2013
2014 if (tech_count++ >= 10) {
2016 }
2017 }
2019
2021
2025
2026 if (tech_count > 10) {
2029 }
2030
2031 /* Toggle techs list button */
2033 current_theme->up_icon,
2034 pwindow->dst,
2035 _("Advances"),
2036 FONTO_DEFAULT, 0);
2038 if (store->show_tree) {
2040 }
2043
2045
2046 dock = list_toggle_button;
2047 store->dock = dock;
2048 } else {
2049 created = FALSE;
2051 pwindow = help_dlg->end_widget_list;
2052 store = (struct techs_buttons *)pwindow->data.ptr;
2053 dock = store->dock;
2054
2055 /* Delete any previous list entries */
2059 }
2060
2061 /* Show/hide techs list */
2063
2064 if (store->show_tree) {
2066 } else {
2068 }
2069
2070 if (store->show_full_tree) {
2071 /* All entries are visible without scrolling */
2075 } else {
2076 int count = help_dlg->scroll->active;
2077
2079 while (advance_label->prev != NULL && --count > 0) {
2081 }
2084 }
2085 }
2086
2087 /* --------------------------------------------------------- */
2088 if (created) {
2089
2091 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
2092 FREESURFACE(surf);
2093 }
2094
2095 area = pwindow->area;
2096
2097 widget_set_position(pwindow,
2098 (main_window_width() - pwindow->size.w) / 2,
2099 (main_window_height() - pwindow->size.h) / 2);
2100
2101 /* Exit button */
2102 close_button = pwindow->prev;
2103 widget_set_position(close_button,
2104 area.x + area.w - close_button->size.w - 1,
2105 pwindow->size.y + adj_size(2));
2106
2107 /* List toggle button */
2108 list_toggle_button = store->dock;
2109 widget_set_position(list_toggle_button, area.x, area.y);
2110
2111 /* List entries */
2113 area.y + list_toggle_button->size.h, 0, 0,
2116 /* Scrollbar */
2117 if (help_dlg->scroll) {
2119 area.x, area.y + list_toggle_button->size.h,
2120 h, FALSE);
2121 }
2122 }
2123
2124 if (store->show_tree) {
2127 } else {
2130 }
2131}
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