Freeciv-3.2
Loading...
Searching...
No Matches
helpdlg.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* SDL2 */
19#ifdef SDL2_PLAIN_INCLUDE
20#include <SDL.h>
21#else /* SDL2_PLAIN_INCLUDE */
22#include <SDL2/SDL.h>
23#endif /* SDL2_PLAIN_INCLUDE */
24
25/* utility */
26#include "fcintl.h"
27#include "log.h"
28
29/* common */
30#include "game.h"
31#include "government.h"
32#include "movement.h"
33
34/* client */
35#include "client_main.h"
36#include "helpdata.h"
37
38/* gui-sdl2 */
39#include "colors.h"
40#include "graphics.h"
41#include "gui_id.h"
42#include "gui_main.h"
43#include "gui_tilespec.h"
44#include "mapview.h"
45#include "repodlgs.h"
46#include "sprite.h"
47#include "themespec.h"
48#include "widget.h"
49
50#include "helpdlg.h"
51
52static struct advanced_dialog *help_dlg = NULL;
53
55 struct widget *targets[6], *sub_targets[6];
57 struct widget *dock;
60};
61
67
69
70static const int bufsz = 8192;
71
72static int change_tech_callback(struct widget *pwidget);
73
74/**********************************************************************/
81
82/**********************************************************************/
93
94/**********************************************************************/
101{
102 log_debug("popup_help_dialog_typed : PORT ME");
103}
104
105/**********************************************************************/
118
119/**********************************************************************/
122static int help_dlg_window_callback(struct widget *pwindow)
123{
124 return -1;
125}
126
127/**********************************************************************/
130static int exit_help_dlg_callback(struct widget *pwidget)
131{
134 flush_dirty();
135 }
136
137 return -1;
138}
139
140/**********************************************************************/
143static int change_gov_callback(struct widget *pwidget)
144{
146 popup_gov_info(MAX_ID - pwidget->id);
147 }
148
149 return -1;
150}
151
152/**********************************************************************/
155void popup_gov_info(int gov)
156{
157}
158
159/**********************************************************************/
162static int change_impr_callback(struct widget *pwidget)
163{
165 popup_impr_info(MAX_ID - pwidget->id);
166 }
167
168 return -1;
169}
170
171/**********************************************************************/
174static void redraw_impr_info_dlg(void)
175{
176 SDL_Color bg_color = {255, 255, 255, 64};
177 struct widget *pwindow = help_dlg->end_widget_list;
178 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
179 SDL_Rect dst;
180
181 redraw_group(pwindow->prev, pwindow, FALSE);
182
183 dst.x = store->dock->prev->size.x - adj_size(10);
184 dst.y = store->dock->prev->size.y - adj_size(10);
185 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
186 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
187
188 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
189
190 create_frame(pwindow->dst->surface,
191 dst.x, dst.y, dst.w, dst.h,
193
194 /*------------------------------------- */
196 widget_flush(pwindow);
197}
198
199/**********************************************************************/
203{
204 SDL_Color bg_color = {255, 255, 255, 128};
205 struct widget *pwindow;
206 struct units_buttons *store;
207 struct widget *close_button = NULL;
210 struct widget *impr_name_label = NULL;
211 struct widget *cost_label = NULL;
212 struct widget *upkeep_label = NULL;
213 struct widget *requirement_label = NULL;
215 struct widget *obsolete_by_label = NULL;
217 struct widget *help_text_label = NULL;
218 struct widget *dock;
220 utf8_str *pstr;
221 SDL_Surface *surf;
222 int h, start_x, start_y, impr_type_count;
223 bool created, text = FALSE;
224 int scrollbar_width = 0;
225 struct impr_type *pimpr_type;
226 char buffer[64000];
227 SDL_Rect area;
228 struct advance *obsTech = NULL;
229
232 }
233
234 if (!help_dlg) {
235 SDL_Surface *background_tmpl, *background, *impr_name, *icon;
236 SDL_Rect dst;
237
239 created = TRUE;
240
241 /* Create dialog */
242 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
243 store = fc_calloc(1, sizeof(struct units_buttons));
244
245 /* Create window */
246 title = create_utf8_from_char_fonto(_("Help : Improvements"),
248 title->style |= TTF_STYLE_BOLD;
249
252 set_wstate(pwindow , FC_WS_NORMAL);
253 pwindow->data.ptr = (void *)store;
254 add_to_gui_list(ID_WINDOW, pwindow);
255
256 help_dlg->end_widget_list = pwindow;
257
258 area = pwindow->area;
259 /* ------------------ */
260
261 /* Close button */
262 close_button = create_themeicon(current_theme->small_cancel_icon,
263 pwindow->dst,
266 close_button->info_label
267 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"),
269 close_button->action = exit_help_dlg_callback;
270 set_wstate(close_button, FC_WS_NORMAL);
271 close_button->key = SDLK_ESCAPE;
272
273 add_to_gui_list(ID_BUTTON, close_button);
274
275 /* ------------------ */
276 dock = close_button;
277
279 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
280
281 /* Background template for entries in scroll list */
284
286 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
288
289 impr_type_count = 0;
290 improvement_iterate(pimprove) {
291
292 /* Copy background surface */
293 background = copy_surface(background_tmpl);
294
295 /* Blit improvement name */
298 dst.x = adj_size(40) + (background->w - impr_name->w - adj_size(40)) / 2;
299 dst.y = (background->h - impr_name->h) / 2;
300 alphablit(impr_name, NULL, background, &dst, 255);
302
303 /* Blit improvement icon */
305 adj_size(36), adj_size(36), 1, TRUE, TRUE);
306 dst.x = adj_size(5);
307 dst.y = (background->h - icon->h) / 2;
308 alphablit(icon, NULL, background, &dst, 255);
309 FREESURFACE(icon);
310
311 improvement_button = create_icon2(background, pwindow->dst,
313
317
318 if (impr_type_count++ >= 10) {
320 }
321
323
325
329
330 if (impr_type_count > 10) {
333 }
334
335 /* Toggle techs list button */
337 current_theme->up_icon,
338 pwindow->dst,
339 _("Improvements"),
340 FONTO_DEFAULT, 0);
341#if 0
343 if (store->show_tree) {
345 }
346#endif
347
350
352
353 dock = list_toggle_button;
354 store->dock = dock;
355 } else {
356 created = FALSE;
358 pwindow = help_dlg->end_widget_list;
359 store = (struct units_buttons *)pwindow->data.ptr;
360 dock = store->dock;
361
362 area = pwindow->area;
363
364 /* Delete any previous list entries */
367 dock->prev);
369 }
370 }
371
373
377 adj_size(48), 1, TRUE, TRUE),
378 pwindow->dst,
381
385
387 sprintf(buffer, "%s %d", _("Base Cost:"),
390 buffer,
391 FONTO_ATTENTION, 0);
392 cost_label->id = ID_LABEL;
395
396 if (!is_wonder(pimpr_type)) {
397 sprintf(buffer, "%s %d", _("Upkeep:"), pimpr_type->upkeep);
399 buffer,
400 FONTO_ATTENTION, 0);
404 }
405 }
406
407 /* Requirement */
409 _("Requirement:"),
410 FONTO_ATTENTION, 0);
414
415 /* FIXME: this should show ranges, negated reqs, and all the
416 * MAX_NUM_REQS reqs.
417 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
418 * definition. */
420 if (!preq->present) {
421 continue;
422 }
425 universal_name_translation(&preq->source, buffer, sizeof(buffer)),
428 if (preq->source.kind != VUT_ADVANCE) {
429 break; /* FIXME */
430 }
431 requirement_label2->id = MAX_ID - advance_number(preq->source.value.advance);
432 requirement_label2->string_utf8->fgcol
433 = *get_tech_color(advance_number(preq->source.value.advance));
436 break;
438
439 if (requirement_label2 == NULL) {
441 Q_("?req:None"),
442 FONTO_ATTENTION, 0);
444 }
445
449
450 /* Obsolete by */
452 _("Obsolete by:"),
453 FONTO_ATTENTION, 0);
457
459 if (pobs->source.kind == VUT_ADVANCE) {
460 obsTech = pobs->source.value.advance;
461 break;
462 }
464
465 if (obsTech == NULL) {
467 _("Never"),
468 FONTO_ATTENTION, 0);
470 } else {
477 obsolete_by_label2->string_utf8->fgcol
481 }
485
486 /* Helptext */
487 start_x = (area.x + 1 + scrollbar_width + help_dlg->end_active_widget_list->size.w + adj_size(20));
488
489 buffer[0] = '\0';
490 helptext_building(buffer, sizeof(buffer), client.conn.playing, NULL,
491 pimpr_type);
492 if (buffer[0] != '\0') {
494
499 text = TRUE;
500 }
501
503
504 /* --------------------------------------------------------- */
505 if (created) {
507 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
508 FREESURFACE(surf);
509 }
510
511 area = pwindow->area;
512
513 widget_set_position(pwindow,
514 (main_window_width() - pwindow->size.w) / 2,
515 (main_window_height() - pwindow->size.h) / 2);
516
517 /* Exit button */
518 close_button = pwindow->prev;
519 widget_set_position(close_button,
520 area.x + area.w - close_button->size.w - 1,
521 pwindow->size.y + adj_size(2));
522
523 /* List toggle button */
524 list_toggle_button = store->dock;
526
527 /* List entries */
529 area.y + list_toggle_button->size.h, 0, 0,
532
533 /* Scrollbar */
534 if (help_dlg->scroll) {
536 area.x, area.y + list_toggle_button->size.h,
537 h, FALSE);
538 }
539 }
540
541 impr_name_label = store->dock->prev;
542 widget_set_position(impr_name_label, start_x, area.y + adj_size(16));
543
544 start_y = impr_name_label->size.y + impr_name_label->size.h + adj_size(10);
545
549 if (!is_wonder(pimpr_type)) {
550 upkeep_label = cost_label->prev;
552 cost_label->size.x + cost_label->size.w + adj_size(20),
553 start_y);
554 }
555 start_y += cost_label->size.h;
556 }
557
560
563 requirement_label->size.x + requirement_label->size.w + adj_size(5),
564 start_y);
565
566 if (store->obsolete_by_button) {
569 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
570 start_y);
571
574 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
575 start_y);
576
577 start_y += obsolete_by_label2->size.h;
578 }
579
580 start_y += adj_size(30);
581
582 if (text) {
584 }
585
587}
588
589/**********************************************************************/
592static int change_unit_callback(struct widget *pwidget)
593{
595 popup_unit_info(MAX_ID - pwidget->id);
596 }
597
598 return -1;
599}
600
601/**********************************************************************/
604static void redraw_unit_info_dlg(void)
605{
606 SDL_Color bg_color = {255, 255, 255, 64};
607 struct widget *pwindow = help_dlg->end_widget_list;
608 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
609 SDL_Rect dst;
610
611 redraw_group(pwindow->prev, pwindow, FALSE);
612
613 dst.x = store->dock->prev->size.x - adj_size(10);
614 dst.y = store->dock->prev->size.y - adj_size(10);
615 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
616 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
617
618 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
619
620 create_frame(pwindow->dst->surface,
621 dst.x, dst.y, dst.w, dst.h,
623
624 /*------------------------------------- */
626 widget_flush(pwindow);
627}
628
629/**********************************************************************/
633{
634 SDL_Color bg_color = {255, 255, 255, 128};
635 struct widget *pwindow;
636 struct units_buttons *store;
637 struct widget *close_button = NULL;
639 struct widget *unit_button = NULL;
640 struct widget *unit_name_label = NULL;
641 struct widget *unit_info_label = NULL;
642 struct widget *requirement_label = NULL;
644 struct widget *obsolete_by_label = NULL;
646 struct widget *help_text_label = NULL;
647 struct widget *dock;
649 utf8_str *pstr;
650 SDL_Surface *surf;
651 int h, start_x, start_y, utype_count;
652 bool created, text = FALSE;
653 int scrollbar_width = 0;
654 struct unit_type *punittype;
655 char buffer[bufsz];
656 SDL_Rect area;
657 struct advance *req;
658
661 }
662
663 /* Create new dialog if it doesn't exist yet */
664 if (!help_dlg) {
665 SDL_Surface *background_tmpl, *background, *unit_name, *icon;
666 SDL_Rect dst;
667
669 created = TRUE;
670
671 /* Create dialog */
672 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
673 store = fc_calloc(1, sizeof(struct units_buttons));
674
675 /* Create window */
677 title->style |= TTF_STYLE_BOLD;
678
681 set_wstate(pwindow , FC_WS_NORMAL);
682 pwindow->data.ptr = (void *)store;
683 add_to_gui_list(ID_WINDOW, pwindow);
684
685 help_dlg->end_widget_list = pwindow;
686
687 area = pwindow->area;
688
689 /* ------------------ */
690
691 /* Close button */
692 close_button = create_themeicon(current_theme->small_cancel_icon,
693 pwindow->dst,
696 close_button->info_label
697 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
698 close_button->action = exit_help_dlg_callback;
699 set_wstate(close_button, FC_WS_NORMAL);
700 close_button->key = SDLK_ESCAPE;
701
702 add_to_gui_list(ID_BUTTON, close_button);
703
704 /* ------------------ */
705 dock = close_button;
706
707 /* --- Create scrollable unit list on the left side ---*/
708
710 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
711
712 /* Background template for entries in scroll list */
715
717 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
719
720 utype_count = 0;
722
723 /* Copy background surface */
724 background = copy_surface(background_tmpl);
725
726 /* Blit unit name */
729 dst.x = adj_size(35) + (background->w - unit_name->w - adj_size(35)) / 2;
730 dst.y = (background->h - unit_name->h) / 2;
731 alphablit(unit_name, NULL, background, &dst, 255);
733
734 /* Blit unit icon */
736 adj_size(36), adj_size(36), 1, TRUE, TRUE);
737 dst.x = (adj_size(35) - icon->w) / 2;
738 dst.y = (background->h - icon->h) / 2;
739 alphablit(icon, NULL, background, &dst, 255);
740 FREESURFACE(icon);
741
742 unit_button = create_icon2(background, pwindow->dst,
744
748
749 if (utype_count++ >= 10) {
751 }
752
754
756
760
761 if (utype_count > 10) {
764 }
765
766 /* Toggle techs list button */
768 current_theme->up_icon,
769 pwindow->dst,
770 _("Units"),
771 FONTO_DEFAULT, 0);
772#if 0
774 if (store->show_tree) {
776 }
777#endif
778
781
783
784 dock = list_toggle_button;
785 store->dock = dock;
786 } else {
787 created = FALSE;
789 pwindow = help_dlg->end_widget_list;
790 store = (struct units_buttons *)pwindow->data.ptr;
791 dock = store->dock;
792
793 area = pwindow->area;
794
795 /* Delete any previous list entries */
798 dock->prev);
800 }
801 }
802
809
813
814 {
815 char buf[2048];
816
817 fc_snprintf(buf, sizeof(buf), "%s %d %s",
819 PL_("shield", "shields", utype_build_shield_cost_base(punittype)));
820
821 if (punittype->pop_cost) {
822 cat_snprintf(buf, sizeof(buf), " %d %s",
823 punittype->pop_cost, PL_("citizen", "citizens",
824 punittype->pop_cost));
825 }
826
827 cat_snprintf(buf, sizeof(buf), " %s", _("Upkeep:"));
828
829 if (punittype->upkeep[O_SHIELD]) {
830 cat_snprintf(buf, sizeof(buf), " %d %s",
831 punittype->upkeep[O_SHIELD], PL_("shield", "shields",
832 punittype->upkeep[O_SHIELD]));
833 }
834 if (punittype->upkeep[O_FOOD]) {
835 cat_snprintf(buf, sizeof(buf), " %d %s",
836 punittype->upkeep[O_FOOD], PL_("food", "foods",
837 punittype->upkeep[O_FOOD]));
838 }
839 if (punittype->upkeep[O_GOLD]) {
840 cat_snprintf(buf, sizeof(buf), " %d %s",
841 punittype->upkeep[O_GOLD], PL_("gold", "golds",
842 punittype->upkeep[O_GOLD]));
843 }
844 if (punittype->happy_cost) {
845 cat_snprintf(buf, sizeof(buf), " %d %s",
846 punittype->happy_cost, PL_("citizen", "citizens",
847 punittype->happy_cost));
848 }
849
850 cat_snprintf(buf, sizeof(buf), "\n%s %d %s %d %s %s\n%s %d %s %d %s %d",
851 _("Attack:"), punittype->attack_strength,
852 _("Defense:"), punittype->defense_strength,
853 _("Move:"), move_points_text(punittype->move_rate, TRUE),
854 _("Vision:"), punittype->vision_radius_sq,
855 _("Firepower:"), punittype->firepower,
856 _("Hitpoints:"), punittype->hp);
857
859 FONTO_ATTENTION, 0);
863 }
864
865 /* Requirement */
867 _("Requirement:"),
868 FONTO_ATTENTION, 0);
872
874
875 if (advance_number(req) == A_NONE) {
877 Q_("?tech:None"),
878 FONTO_ATTENTION, 0);
880 } else {
882
889 requirement_label2->string_utf8->fgcol = *get_tech_color(req_id);
892 }
896
897 /* Obsolete by */
899 _("Obsolete by:"),
900 FONTO_ATTENTION, 0);
904
905 if (punittype->obsoleted_by == U_NOT_OBSOLETED) {
907 Q_("?utype:None"),
908 FONTO_ATTENTION, 0);
910 } else {
911 const struct unit_type *utype = punittype->obsoleted_by;
912 struct advance *obs_req = utype_primary_tech_req(utype);
913
919 obsolete_by_label2->string_utf8->fgcol
924 }
926 dock = obsolete_by_label2;
928
929 /* Helptext */
930 start_x = (area.x + 1 + scrollbar_width + help_dlg->active_widget_list->size.w + adj_size(20));
931
932 buffer[0] = '\0';
933 helptext_unit(buffer, sizeof(buffer), client.conn.playing, "", utype_by_number(type_id),
934 TRUE);
935 if (buffer[0] != '\0') {
937
942 text = TRUE;
943 }
944
946
947 /* --------------------------------------------------------- */
948 if (created) {
949
951 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
952 FREESURFACE(surf);
953 }
954
955 area = pwindow->area;
956
957 widget_set_position(pwindow,
958 (main_window_width() - pwindow->size.w) / 2,
959 (main_window_height() - pwindow->size.h) / 2);
960
961 /* Exit button */
962 close_button = pwindow->prev;
963 widget_set_position(close_button,
964 area.x + area.w - close_button->size.w - 1,
965 pwindow->size.y + adj_size(2));
966
967 /* List toggle button */
968 list_toggle_button = store->dock;
970
971 /* List entries */
973 area.y + list_toggle_button->size.h, 0, 0,
976
977 /* Scrollbar */
978 if (help_dlg->scroll) {
980 area.x, area.y + list_toggle_button->size.h,
981 h, FALSE);
982 }
983 }
984
985 unit_name_label = store->dock->prev;
986 widget_set_position(unit_name_label, start_x, area.y + adj_size(16));
987
988 start_y = unit_name_label->size.y + unit_name_label->size.h + adj_size(10);
989
992
993 start_y += unit_info_label->size.h;
994
997
1000 requirement_label->size.x + requirement_label->size.w + adj_size(5),
1001 start_y);
1002
1005 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
1006 start_y);
1007
1010 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
1011 start_y);
1012
1013 start_y += obsolete_by_label2->size.h + adj_size(20);
1014
1015 if (text) {
1018 }
1019
1021}
1022
1023/* =============================================== */
1024/* ==================== Tech Tree ================ */
1025/* =============================================== */
1026
1027/**********************************************************************/
1030static int change_tech_callback(struct widget *pwidget)
1031{
1033 popup_tech_info(MAX_ID - pwidget->id);
1034 }
1035
1036 return -1;
1037}
1038
1039/**********************************************************************/
1042static int show_tech_tree_callback(struct widget *pwidget)
1043{
1045 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1046
1047 store->show_tree = !store->show_tree;
1048 if (!store->show_tree) {
1049 store->show_full_tree = FALSE;
1050 store->dock->theme2 = current_theme->up_icon;
1051 }
1052 popup_tech_info(MAX_ID - store->dock->prev->id);
1053 }
1054
1055 return -1;
1056}
1057
1058/**********************************************************************/
1061static void redraw_tech_info_dlg(void)
1062{
1063 SDL_Color bg_color = {255, 255, 255, 64};
1064 struct widget *pwindow = help_dlg->end_widget_list;
1065 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1067 utf8_str *pstr;
1068 SDL_Rect dst;
1069
1070 redraw_group(pwindow->prev, pwindow, FALSE);
1071
1072 dst.x = store->dock->prev->prev->size.x - adj_size(10);
1073 dst.y = store->dock->prev->prev->size.y - adj_size(10);
1074 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
1075 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
1076
1077 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1078
1079 create_frame(pwindow->dst->surface,
1080 dst.x, dst.y, dst.w, dst.h,
1082
1083 /* -------------------------- */
1085 pstr->style |= TTF_STYLE_BOLD;
1086
1088 dst.x = store->dock->prev->prev->size.x;
1089 if (store->targets[0]) {
1090 dst.y = store->targets[0]->size.y - text0->h;
1091 } else {
1092 dst.y = store->dock->prev->prev->size.y
1093 + store->dock->prev->prev->size.h + adj_size(10);
1094 }
1095
1096 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1098
1099 if (store->sub_targets[0]) {
1100 int i;
1101
1103
1104 copy_chars_to_utf8_str(pstr, _("( with "));
1106
1109 i = 0;
1111 dst.x = store->sub_targets[i]->size.x - text0->w;
1112 dst.y = store->sub_targets[i]->size.y;
1113
1114 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1115 dst.x = store->sub_targets[i]->size.x + store->sub_targets[i]->size.w;
1116 dst.y = store->sub_targets[i]->size.y;
1117
1118 alphablit(text1, NULL, pwindow->dst->surface, &dst, 255);
1119 i++;
1120 }
1121
1124 }
1126
1128 widget_flush(pwindow);
1129}
1130
1131/**********************************************************************/
1135 struct widget *pwindow,
1136 struct techs_buttons *store)
1137{
1138 struct widget *pwidget;
1139 struct widget *last, *budynki;
1140 struct widget *dock = store->dock;
1142 int start_x, start_y, imp_count, unit_count, flags_count, gov_count;
1143 char buffer[bufsz];
1144 SDL_Surface *surf;
1145
1146 start_x = (pwindow->area.x + adj_size(1) + width + help_dlg->active_widget_list->size.w + adj_size(20));
1147
1148 /* Tech tree icon */
1149 pwidget = create_icon2(current_theme->tech_tree_icon, pwindow->dst,
1151
1152 set_wstate(pwidget, FC_WS_NORMAL);
1154 pwidget->id = MAX_ID - tech;
1155 widget_add_as_prev(pwidget, dock);
1156 dock = pwidget;
1157
1158 /* Tech name (heading) */
1159 pwidget
1161 pwindow->dst,
1164
1165 pwidget->id = ID_LABEL;
1166 widget_add_as_prev(pwidget, dock);
1167 dock = pwidget;
1168
1169 /* Target techs */
1170 targets_count = 0;
1172 if ((targets_count < 6)
1173 && (advance_required(aidx, AR_ONE) == tech
1174 || advance_required(aidx, AR_TWO) == tech)) {
1175 pwidget
1180 pwidget->string_utf8->fgcol = *get_tech_color(aidx);
1181 max_width = MAX(max_width, pwidget->size.w);
1182 set_wstate(pwidget, FC_WS_NORMAL);
1183 pwidget->action = change_tech_callback;
1184 pwidget->id = MAX_ID - aidx;
1185 widget_add_as_prev(pwidget, dock);
1186 dock = pwidget;
1187 store->targets[targets_count++] = pwidget;
1188 }
1190 if (targets_count < 6) {
1191 store->targets[targets_count] = NULL;
1192 }
1193
1195 if (targets_count > 0) {
1196 int sub_tech;
1197
1198 for (i = 0; i < targets_count; i++) {
1199 sub_tech = MAX_ID - store->targets[i]->id;
1200 if (advance_required(sub_tech, AR_ONE) == tech
1203 } else if (advance_required(sub_tech, AR_TWO) == tech
1206 } else {
1207 continue;
1208 }
1209 pwidget
1215 set_wstate(pwidget, FC_WS_NORMAL);
1216 pwidget->action = change_tech_callback;
1217 pwidget->id = MAX_ID - sub_tech;
1218 widget_add_as_prev(pwidget, dock);
1219 dock = pwidget;
1220 store->sub_targets[sub_targets_count++] = pwidget;
1221 }
1222 }
1223 if (sub_targets_count < 6) {
1225 }
1226
1227 /* Fill array with iprvm. icons */
1228 budynki = pwidget;
1229
1230 /* Target governments */
1231 gov_count = 0;
1232 governments_iterate(gov) {
1233 requirement_vector_iterate(&(gov->reqs), preq) {
1234 if (VUT_ADVANCE == preq->source.kind
1235 && advance_number(preq->source.value.advance) == tech) {
1236
1237 pwidget
1239 pwindow->dst,
1243 set_wstate(pwidget, FC_WS_NORMAL);
1244 pwidget->action = change_gov_callback;
1245 pwidget->id = MAX_ID - government_index(gov);
1246 widget_add_as_prev(pwidget, dock);
1247 dock = pwidget;
1248 gov_count++;
1249 }
1252
1253 /* Target improvements */
1254 imp_count = 0;
1255 improvement_iterate(pimprove) {
1256 if (valid_improvement(pimprove)) {
1257 /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs.
1258 * Currently it's limited to 1 req. Remember MAX_NUM_REQS is a compile-time
1259 * definition. */
1260 requirement_vector_iterate(&(pimprove->reqs), preq) {
1261 if (VUT_ADVANCE == preq->source.kind
1262 && advance_number(preq->source.value.advance) == tech) {
1263 surf = get_building_surface(pimprove);
1265 resize_surface_box(surf, adj_size(48), adj_size(48), 1, TRUE,
1266 TRUE),
1267 pwindow->dst,
1271 set_wstate(pwidget, FC_WS_NORMAL);
1272 if (is_wonder(pimprove)) {
1274 }
1275 pwidget->action = change_impr_callback;
1276 pwidget->id = MAX_ID - improvement_number(pimprove);
1277 widget_add_as_prev(pwidget, dock);
1278 dock = pwidget;
1279 imp_count++;
1280 }
1281
1282 break;
1284 }
1286
1287 unit_count = 0;
1292 adj_size(48), adj_size(48), 1, TRUE, TRUE),
1295 set_wstate(pwidget, FC_WS_NORMAL);
1296 pwidget->action = change_unit_callback;
1297 pwidget->id = MAX_ID - utype_number(un);
1298 widget_add_as_prev(pwidget, dock);
1299 dock = pwidget;
1300 unit_count++;
1301 }
1303
1304 buffer[0] = '\0';
1305 if (tech != A_NONE) {
1306 helptext_advance(buffer, sizeof(buffer), client.conn.playing, "", tech);
1307 }
1308 if (buffer[0] != '\0') {
1310
1312 pwidget = create_iconlabel(NULL, pwindow->dst, pstr, 0);
1313 pwidget->id = ID_LABEL;
1314 widget_add_as_prev(pwidget, dock);
1315 flags_count = 1;
1316 } else {
1317 flags_count = 0;
1318 }
1319
1320 last = pwidget;
1321 /* --------------------------------------------- */
1322
1323 /* Tree button */
1324 pwidget = store->dock->prev;
1325 pwidget->size.x = pwindow->area.x + pwindow->area.w - pwidget->size.w - adj_size(17);
1326 pwidget->size.y = pwindow->area.y + adj_size(16);
1327
1328 /* Tech label */
1329 pwidget = pwidget->prev;
1330 pwidget->size.x = start_x;
1331 pwidget->size.y = pwindow->area.y + adj_size(16);
1332 start_y = pwidget->size.y + pwidget->size.h + adj_size(30);
1333
1334 if (targets_count) {
1335 int j = 0;
1336
1337 i = 0;
1338
1339 while (i < 6 && store->targets[i]) {
1340 store->targets[i]->size.x = pwindow->size.x + start_x;
1341 store->targets[i]->size.y = start_y;
1342
1343 if (store->sub_targets[j]) {
1344 int t0 = MAX_ID - store->targets[i]->id;
1345 int t1 = MAX_ID - store->sub_targets[j]->id;
1346
1347 if (advance_required(t0, AR_ONE) == t1
1348 || advance_required(t0, AR_TWO) == t1) {
1349 store->sub_targets[j]->size.x = pwindow->size.x + start_x + max_width + 60;
1350 store->sub_targets[j]->size.y = store->targets[i]->size.y;
1351 j++;
1352 }
1353 }
1354
1355 start_y += store->targets[i]->size.h;
1356 i++;
1357 }
1358
1359 start_y += adj_size(10);
1360 }
1361 pwidget = NULL;
1362
1363 if (gov_count) {
1364 pwidget = budynki->prev;
1365 while (gov_count-- && pwidget) {
1366 pwidget->size.x = pwindow->size.x + start_x;
1367 pwidget->size.y = start_y;
1368 start_y += pwidget->size.h + adj_size(2);
1369 pwidget = pwidget->prev;
1370 }
1371 }
1372
1373 if (imp_count) {
1374 if (!pwidget) {
1375 pwidget = budynki->prev;
1376 }
1377 while (imp_count-- && pwidget) {
1378 pwidget->size.x = pwindow->size.x + start_x;
1379 pwidget->size.y = start_y;
1380 start_y += pwidget->size.h + adj_size(2);
1381 pwidget = pwidget->prev;
1382 }
1383 }
1384
1385 if (unit_count) {
1386 if (!pwidget) {
1387 pwidget = budynki->prev;
1388 }
1389 while (unit_count-- && pwidget) {
1390 pwidget->size.x = pwindow->size.x + start_x;
1391 pwidget->size.y = start_y;
1392 start_y += pwidget->size.h + adj_size(2);
1393 pwidget = pwidget->prev;
1394 }
1395 }
1396
1397 if (flags_count) {
1398 if (!pwidget) {
1399 pwidget = budynki->prev;
1400 }
1401 while (flags_count-- && pwidget) {
1402 pwidget->size.x = pwindow->size.x + start_x;
1403 pwidget->size.y = start_y;
1404 start_y += pwidget->size.h + adj_size(2);
1405 pwidget = pwidget->prev;
1406 }
1407 }
1408
1409 return last;
1410}
1411
1412/**********************************************************************/
1415static void redraw_tech_tree_dlg(void)
1416{
1418 SDL_Color bg_color = {255, 255, 255, 64};
1419 struct widget *pwindow = help_dlg->end_widget_list;
1420 struct widget *sub0, *sub1;
1421 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1422 struct widget *ptech = store->dock->prev;
1423 int i,j, tech, count;
1424 int step;
1425 int mod;
1426 SDL_Rect dst;
1427
1428 /* Redraw Window with exit button */
1429 redraw_group(pwindow->prev, pwindow, FALSE);
1430
1431 dst.x = pwindow->area.x + pwindow->area.w - adj_size(459) - adj_size(7);
1432 dst.y = pwindow->area.y + adj_size(6);
1433 dst.w = pwindow->area.w - (dst.x - pwindow->area.x) - adj_size(10);
1434 dst.h = pwindow->area.h - (dst.y - pwindow->area.y) - adj_size(10);
1435
1436 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1437
1438 create_frame(pwindow->dst->surface,
1439 dst.x, dst.y, dst.w, dst.h,
1441
1442 /* Draw req arrows */
1443 i = 0;
1444 while (i < 4 && store->sub_req[i]) {
1445 i++;
1446 }
1447 count = i;
1448
1449 i = 0;
1450 while (i < 2 && store->requirement_button[i]) {
1451 tech = MAX_ID - store->requirement_button[i]->id;
1452
1453 /* Find sub req's */
1454 if (i) {
1455 sub0 = NULL;
1456 for (j = count - 1; j >= 0; j--) {
1457 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1458 sub0 = store->sub_req[j];
1459 break;
1460 }
1461 }
1462
1463 sub1 = NULL;
1464 for (j = count - 1; j >= 0; j--) {
1465 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1466 sub1 = store->sub_req[j];
1467 break;
1468 }
1469 }
1470 } else {
1471 sub0 = NULL;
1472 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1473 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1474 sub0 = store->sub_req[j];
1475 break;
1476 }
1477 }
1478
1479 sub1 = NULL;
1480 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1481 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1482 sub1 = store->sub_req[j];
1483 break;
1484 }
1485 }
1486 }
1487
1488 /* Draw main Arrow */
1490 store->requirement_button[i]->size.x + store->requirement_button[i]->size.w,
1491 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1492 ptech->size.x,
1493 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1494 line_color);
1495
1496 /* Draw sub req arrows */
1497 if (sub0 || sub1) {
1499 store->requirement_button[i]->size.x - adj_size(10),
1500 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1501 store->requirement_button[i]->size.x ,
1502 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1503 line_color);
1504 }
1505
1506 if (sub0) {
1508 store->requirement_button[i]->size.x - adj_size(10),
1509 sub0->size.y + sub0->size.h / 2,
1510 store->requirement_button[i]->size.x - adj_size(10),
1511 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1512 line_color);
1514 sub0->size.x + sub0->size.w,
1515 sub0->size.y + sub0->size.h / 2,
1516 store->requirement_button[i]->size.x - adj_size(10),
1517 sub0->size.y + sub0->size.h / 2,
1518 line_color);
1519 }
1520
1521 if (sub1) {
1523 store->requirement_button[i]->size.x - adj_size(10),
1524 sub1->size.y + sub1->size.h / 2,
1525 store->requirement_button[i]->size.x - adj_size(10),
1526 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1527 line_color);
1529 sub1->size.x + sub1->size.w,
1530 sub1->size.y + sub1->size.h / 2,
1531 store->requirement_button[i]->size.x - adj_size(10),
1532 sub1->size.y + sub1->size.h / 2,
1533 line_color);
1534 }
1535 i++;
1536 }
1537
1538 i = 0;
1539 while (i < 6 && store->targets[i]) {
1540 i++;
1541 }
1542 count = i;
1543
1544 if (count > 4) {
1545 mod = 3;
1546 } else {
1547 mod = 2;
1548 }
1549
1550 for (i = 0; i < count; i++) {
1551 tech = MAX_ID - store->targets[i]->id;
1552 step = ptech->size.h / (count + 1);
1553
1554 switch ((i % mod)) {
1555 case 2:
1557 break;
1558 case 1:
1560 break;
1561 default:
1563 break;
1564 }
1565
1566 /* Find sub reqs */
1567 if (advance_required(tech, AR_ONE) == MAX_ID - ptech->id) {
1568 sub0 = ptech;
1569 } else {
1570 sub0 = NULL;
1571 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1572 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_ONE)) {
1573 sub0 = store->sub_targets[j];
1574 break;
1575 }
1576 }
1577 }
1578
1579 if (advance_required(tech, AR_TWO) == MAX_ID - ptech->id) {
1580 sub1 = ptech;
1581 } else {
1582 sub1 = NULL;
1583 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1584 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_TWO)) {
1585 sub1 = store->sub_targets[j];
1586 break;
1587 }
1588 }
1589 }
1590
1591 /* Draw sub targets arrows */
1592 if (sub0 || sub1) {
1593 create_line(store->targets[i]->dst->surface,
1594 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1595 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1596 store->targets[i]->size.x ,
1597 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1598 line_color);
1599 }
1600
1601 if (sub0) {
1602 int y;
1603
1604 if (sub0 == ptech) {
1605 y = sub0->size.y + step * (i + 1);
1606 } else {
1607 y = sub0->size.y + sub0->size.h / 2;
1608 }
1609
1610 create_line(store->targets[i]->dst->surface,
1611 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1612 y,
1613 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1614 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1615 line_color);
1616 create_line(store->targets[i]->dst->surface,
1617 sub0->size.x + sub0->size.w,
1618 y,
1619 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1620 y,
1621 line_color);
1622 }
1623
1624 if (sub1) {
1625 int y;
1626
1627 if (sub1 == ptech) {
1628 y = sub1->size.y + step * (i + 1);
1629 } else {
1630 y = sub1->size.y + sub1->size.h / 2;
1631 }
1632
1633 create_line(store->targets[i]->dst->surface,
1634 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1635 y,
1636 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1637 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1638 line_color);
1639 create_line(store->targets[i]->dst->surface,
1640 sub1->size.x + sub1->size.w,
1641 y,
1642 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1643 y,
1644 line_color);
1645 }
1646 }
1647
1648 /* Redraw rest */
1650
1651 widget_flush(pwindow);
1652}
1653
1654/**********************************************************************/
1658{
1660 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1661
1662 if (store->show_full_tree) {
1663 pwidget->theme2 = current_theme->up_icon;
1664 } else {
1665 pwidget->theme2 = current_theme->down_icon;
1666 }
1667 store->show_full_tree = !store->show_full_tree;
1668 popup_tech_info(MAX_ID - store->dock->prev->id);
1669 }
1670
1671 return -1;
1672}
1673
1674/**********************************************************************/
1678 struct widget *pwindow,
1679 struct techs_buttons *store)
1680{
1682 struct widget *pwidget;
1683 struct widget *ptech;
1684 utf8_str *pstr;
1685 SDL_Surface *surf;
1686 struct widget *dock = store->dock;
1687
1689 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1690
1693 pwidget = create_icon2(surf, pwindow->dst,
1695
1696 set_wstate(pwidget, FC_WS_NORMAL);
1698 pwidget->id = MAX_ID - tech;
1699 widget_add_as_prev(pwidget, dock);
1700 ptech = pwidget;
1701 dock = pwidget;
1702
1703 req_count = 0;
1704 for (i = AR_ONE; i <= AR_TWO; i++) {
1707
1708 if (NULL != vap && A_NONE != ar) {
1711 pwidget = create_icon2(surf, pwindow->dst,
1713 set_wstate(pwidget, FC_WS_NORMAL);
1714 pwidget->action = change_tech_callback;
1715 pwidget->id = MAX_ID - ar;
1716 widget_add_as_prev(pwidget, dock);
1717 dock = pwidget;
1718 store->requirement_button[req_count++] = pwidget;
1719 }
1720 }
1721
1722 sub_req_count = 0;
1723
1724 if (store->show_full_tree && req_count > 0) {
1725 int j, sub_tech;
1726
1727 for (j = 0; j < req_count; j++) {
1728 sub_tech = MAX_ID - store->requirement_button[j]->id;
1729 for (i = AR_ONE; i <= AR_TWO; i++) {
1732
1733 if (NULL != vap && A_NONE != ar) {
1736 pwidget = create_icon2(surf, pwindow->dst,
1738 set_wstate(pwidget, FC_WS_NORMAL);
1739 pwidget->action = change_tech_callback;
1740 pwidget->id = MAX_ID - ar;
1741 widget_add_as_prev(pwidget, dock);
1742 dock = pwidget;
1743 store->sub_req[sub_req_count++] = pwidget;
1744 }
1745 }
1746 }
1747 }
1748
1749 if (sub_req_count < 4) {
1750 store->sub_req[sub_req_count] = NULL;
1751 }
1752
1753 targets_count = 0;
1755 if ((targets_count < 6)
1756 && (advance_required(aidx, AR_ONE) == tech
1757 || advance_required(aidx, AR_TWO) == tech)) {
1760 pwidget = create_icon2(surf, pwindow->dst,
1762
1763 set_wstate(pwidget, FC_WS_NORMAL);
1764 pwidget->action = change_tech_callback;
1765 pwidget->id = MAX_ID - aidx;
1766 widget_add_as_prev(pwidget, dock);
1767 dock = pwidget;
1768 store->targets[targets_count++] = pwidget;
1769 }
1771 if (targets_count < 6) {
1772 store->targets[targets_count] = NULL;
1773 }
1774
1776 if (targets_count > 0) {
1777 int sub_tech;
1778
1779 for (i = 0; i < targets_count; i++) {
1780 sub_tech = MAX_ID - store->targets[i]->id;
1781 if (advance_required(sub_tech, AR_ONE) == tech
1784 } else if (advance_required(sub_tech, AR_TWO) == tech
1787 } else {
1788 continue;
1789 }
1790
1793 pwidget = create_icon2(surf, pwindow->dst,
1795 set_wstate(pwidget, FC_WS_NORMAL);
1796 pwidget->action = change_tech_callback;
1797 pwidget->id = MAX_ID - sub_tech;
1798 widget_add_as_prev(pwidget, dock);
1799 dock = pwidget;
1800 store->sub_targets[sub_targets_count++] = pwidget;
1801 }
1802 }
1803 if (sub_targets_count < 6) {
1805 }
1806
1808
1809 /* ------------------------------------------ */
1810 if (sub_req_count > 0) {
1811 w = (adj_size(20) + store->sub_req[0]->size.w) * 2;
1812 w += (pwindow->size.w - (20 + store->sub_req[0]->size.w + w + ptech->size.w)) / 2;
1813 } else {
1814 if (req_count > 0) {
1815 w = (pwindow->area.x + 1
1816 + width + store->requirement_button[0]->size.w * 2 + adj_size(20));
1817 w += (pwindow->size.w - ((adj_size(20) + store->requirement_button[0]->size.w)
1818 + w + ptech->size.w)) / 2;
1819 } else {
1820 w = (pwindow->size.w - ptech->size.w) / 2;
1821 }
1822 }
1823
1824 ptech->size.x = pwindow->size.x + w;
1825 ptech->size.y = pwindow->area.y + (pwindow->area.h - ptech->size.h) / 2;
1826
1827 if (req_count > 0) {
1828 h = (req_count == 1 ? store->requirement_button[0]->size.h :
1829 req_count * (store->requirement_button[0]->size.h + adj_size(80)) - adj_size(80));
1830 h = ptech->size.y + (ptech->size.h - h) / 2;
1831 for (i = 0; i < req_count; i++) {
1832 store->requirement_button[i]->size.x
1833 = ptech->size.x - adj_size(20) - store->requirement_button[i]->size.w;
1834 store->requirement_button[i]->size.y = h;
1835 h += (store->requirement_button[i]->size.h + adj_size(80));
1836 }
1837 }
1838
1839 if (sub_req_count > 0) {
1840 h = (sub_req_count == 1 ? store->sub_req[0]->size.h :
1841 sub_req_count * (store->sub_req[0]->size.h + adj_size(20)) - adj_size(20));
1842 h = ptech->size.y + (ptech->size.h - h) / 2;
1843 for (i = 0; i < sub_req_count; i++) {
1844 store->sub_req[i]->size.x
1845 = ptech->size.x - (adj_size(20) + store->sub_req[i]->size.w) * 2;
1846 store->sub_req[i]->size.y = h;
1847 h += (store->sub_req[i]->size.h + adj_size(20));
1848 }
1849 }
1850
1851 if (targets_count > 0) {
1852 h = (targets_count == 1 ? store->targets[0]->size.h :
1853 targets_count * (store->targets[0]->size.h + adj_size(20)) - adj_size(20));
1854 h = ptech->size.y + (ptech->size.h - h) / 2;
1855 for (i = 0; i < targets_count; i++) {
1856 store->targets[i]->size.x = ptech->size.x + ptech->size.w + adj_size(20);
1857 store->targets[i]->size.y = h;
1858 h += (store->targets[i]->size.h + adj_size(20));
1859 }
1860 }
1861
1862 if (sub_targets_count > 0) {
1863 if (sub_targets_count < 3) {
1864 store->sub_targets[0]->size.x
1865 = ptech->size.x + ptech->size.w - store->sub_targets[0]->size.w;
1866 store->sub_targets[0]->size.y
1867 = ptech->size.y - store->sub_targets[0]->size.h - adj_size(10);
1868 if (store->sub_targets[1]) {
1869 store->sub_targets[1]->size.x
1870 = ptech->size.x + ptech->size.w - store->sub_targets[1]->size.w;
1871 store->sub_targets[1]->size.y = ptech->size.y + ptech->size.h + adj_size(10);
1872 }
1873 } else {
1874 if (sub_targets_count < 5) {
1875 for (i = 0; i < MIN(sub_targets_count, 4); i++) {
1876 store->sub_targets[i]->size.x
1877 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1878 if (i < 2) {
1879 store->sub_targets[i]->size.y
1880 = ptech->size.y - (store->sub_targets[i]->size.h + adj_size(5)) * (2 - i);
1881 } else {
1882 store->sub_targets[i]->size.y
1883 = ptech->size.y + ptech->size.h + adj_size(5)
1884 + (store->sub_targets[i]->size.h + adj_size(5)) * (i - 2);
1885 }
1886 }
1887 } else {
1888 h = (store->sub_targets[0]->size.h + adj_size(6));
1889 for (i = 0; i < MIN(sub_targets_count, 6); i++) {
1890 switch (i) {
1891 case 0:
1892 store->sub_targets[i]->size.x
1893 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1894 store->sub_targets[i]->size.y = ptech->size.y - h * 2;
1895 break;
1896 case 1:
1897 store->sub_targets[i]->size.x
1898 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1899 - adj_size(10);
1900 store->sub_targets[i]->size.y = ptech->size.y - h - h / 2;
1901 break;
1902 case 2:
1903 store->sub_targets[i]->size.x
1904 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1905 store->sub_targets[i]->size.y = ptech->size.y - h;
1906 break;
1907 case 3:
1908 store->sub_targets[i]->size.x
1909 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1910 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6);
1911 break;
1912 case 4:
1913 store->sub_targets[i]->size.x
1914 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1915 store->sub_targets[i]->size.y = ptech->size.y + ptech->size.h + adj_size(6) + h;
1916 break;
1917 default:
1918 store->sub_targets[i]->size.x
1919 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1920 - adj_size(10);
1921 store->sub_targets[i]->size.y
1922 = ptech->size.y + ptech->size.h + adj_size(6) + h / 2 ;
1923 break;
1924 }
1925 }
1926 }
1927 }
1928 }
1929
1930 return pwidget;
1931}
1932
1933/**********************************************************************/
1937{
1938 struct widget *pwindow;
1939 struct techs_buttons *store;
1940 struct widget *close_button = NULL;
1941 struct widget *advance_label = NULL;
1942 struct widget *list_toggle_button = NULL;
1943 struct widget *dock;
1944 utf8_str *title;
1945 utf8_str *pstr;
1946 SDL_Surface *surf;
1947 int h, tech_count;
1948 bool created;
1949 int scrollbar_width = 0;
1950 SDL_Rect area;
1951
1952 if (current_help_dlg != HELP_TECH) {
1954 }
1955
1956 /* Create new dialog if it doesn't exist yet */
1957 if (!help_dlg) {
1959 created = TRUE;
1960
1961 /* Create dialog */
1962 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
1963 store = fc_calloc(1, sizeof(struct techs_buttons));
1964
1965 store->show_tree = FALSE;
1966 store->show_full_tree = FALSE;
1967
1968 /* Create window */
1969 title = create_utf8_from_char_fonto(_("Help : Advances Tree"),
1971 title->style |= TTF_STYLE_BOLD;
1972
1974 pwindow->data.ptr = (void *)store;
1976 set_wstate(pwindow, FC_WS_NORMAL);
1977
1978 add_to_gui_list(ID_WINDOW, pwindow);
1979
1980 help_dlg->end_widget_list = pwindow;
1981
1982 /* ------------------ */
1983
1984 /* Close button */
1985 close_button = create_themeicon(current_theme->small_cancel_icon, pwindow->dst,
1988 close_button->info_label
1989 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
1990 close_button->action = exit_help_dlg_callback;
1991 set_wstate(close_button, FC_WS_NORMAL);
1992 close_button->key = SDLK_ESCAPE;
1993
1994 add_to_gui_list(ID_BUTTON, close_button);
1995
1996 /* ------------------ */
1997 dock = close_button;
1998
1999 /* --- Create scrollable advance list on the left side ---*/
2001 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
2002
2003 tech_count = 0;
2006
2007 if (vap) {
2010 advance_label = create_icon2(surf, pwindow->dst,
2012
2016
2017 if (tech_count++ >= 10) {
2019 }
2020 }
2022
2024
2028
2029 if (tech_count > 10) {
2032 }
2033
2034 /* Toggle techs list button */
2036 current_theme->up_icon,
2037 pwindow->dst,
2038 _("Advances"),
2039 FONTO_DEFAULT, 0);
2041 if (store->show_tree) {
2043 }
2046
2048
2049 dock = list_toggle_button;
2050 store->dock = dock;
2051 } else {
2052 created = FALSE;
2054 pwindow = help_dlg->end_widget_list;
2055 store = (struct techs_buttons *)pwindow->data.ptr;
2056 dock = store->dock;
2057
2058 /* Delete any previous list entries */
2062 }
2063
2064 /* Show/hide techs list */
2066
2067 if (store->show_tree) {
2069 } else {
2071 }
2072
2073 if (store->show_full_tree) {
2074 /* All entries are visible without scrolling */
2078 } else {
2079 int count = help_dlg->scroll->active;
2080
2082 while (advance_label->prev != NULL && --count > 0) {
2084 }
2087 }
2088 }
2089
2090 /* --------------------------------------------------------- */
2091 if (created) {
2092
2094 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
2095 FREESURFACE(surf);
2096 }
2097
2098 area = pwindow->area;
2099
2100 widget_set_position(pwindow,
2101 (main_window_width() - pwindow->size.w) / 2,
2102 (main_window_height() - pwindow->size.h) / 2);
2103
2104 /* Exit button */
2105 close_button = pwindow->prev;
2106 widget_set_position(close_button,
2107 area.x + area.w - close_button->size.w - 1,
2108 pwindow->size.y + adj_size(2));
2109
2110 /* List toggle button */
2111 list_toggle_button = store->dock;
2112 widget_set_position(list_toggle_button, area.x, area.y);
2113
2114 /* List entries */
2116 area.y + list_toggle_button->size.h, 0, 0,
2119 /* Scrollbar */
2120 if (help_dlg->scroll) {
2122 area.x, area.y + list_toggle_button->size.h,
2123 h, FALSE);
2124 }
2125 }
2126
2127 if (store->show_tree) {
2130 } else {
2133 }
2134}
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