Freeciv-3.3
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 reqs.
413 * Currently it's limited to 1 req. */
415 if (!preq->present) {
416 continue;
417 }
420 universal_name_translation(&preq->source, buffer, sizeof(buffer)),
423 if (preq->source.kind != VUT_ADVANCE) {
424 break; /* FIXME */
425 }
426 requirement_label2->id = MAX_ID - advance_number(preq->source.value.advance);
427 requirement_label2->string_utf8->fgcol
428 = *get_tech_color(advance_number(preq->source.value.advance));
431 break;
433
434 if (requirement_label2 == NULL) {
436 Q_("?req:None"),
437 FONTO_ATTENTION, 0);
439 }
440
444
445 /* Obsolete by */
447 _("Obsolete by:"),
448 FONTO_ATTENTION, 0);
452
454 if (pobs->source.kind == VUT_ADVANCE) {
455 obsTech = pobs->source.value.advance;
456 break;
457 }
459
460 if (obsTech == NULL) {
462 _("Never"),
463 FONTO_ATTENTION, 0);
465 } else {
472 obsolete_by_label2->string_utf8->fgcol
476 }
480
481 /* Helptext */
482 start_x = (area.x + 1 + scrollbar_width + help_dlg->end_active_widget_list->size.w + adj_size(20));
483
484 buffer[0] = '\0';
485 helptext_building(buffer, sizeof(buffer), client.conn.playing, NULL,
486 pimpr_type);
487 if (buffer[0] != '\0') {
489
494 text = TRUE;
495 }
496
498
499 /* --------------------------------------------------------- */
500 if (created) {
502 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
503 FREESURFACE(surf);
504 }
505
506 area = pwindow->area;
507
508 widget_set_position(pwindow,
509 (main_window_width() - pwindow->size.w) / 2,
510 (main_window_height() - pwindow->size.h) / 2);
511
512 /* Exit button */
513 close_button = pwindow->prev;
514 widget_set_position(close_button,
515 area.x + area.w - close_button->size.w - 1,
516 pwindow->size.y + adj_size(2));
517
518 /* List toggle button */
519 list_toggle_button = store->dock;
521
522 /* List entries */
524 area.y + list_toggle_button->size.h, 0, 0,
527
528 /* Scrollbar */
529 if (help_dlg->scroll) {
531 area.x, area.y + list_toggle_button->size.h,
532 h, FALSE);
533 }
534 }
535
536 impr_name_label = store->dock->prev;
537 widget_set_position(impr_name_label, start_x, area.y + adj_size(16));
538
539 start_y = impr_name_label->size.y + impr_name_label->size.h + adj_size(10);
540
544 if (!is_wonder(pimpr_type)) {
545 upkeep_label = cost_label->prev;
547 cost_label->size.x + cost_label->size.w + adj_size(20),
548 start_y);
549 }
550 start_y += cost_label->size.h;
551 }
552
555
558 requirement_label->size.x + requirement_label->size.w + adj_size(5),
559 start_y);
560
561 if (store->obsolete_by_button) {
564 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
565 start_y);
566
569 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
570 start_y);
571
572 start_y += obsolete_by_label2->size.h;
573 }
574
575 start_y += adj_size(30);
576
577 if (text) {
579 }
580
582}
583
584/**********************************************************************/
587static int change_unit_callback(struct widget *pwidget)
588{
590 popup_unit_info(MAX_ID - pwidget->id);
591 }
592
593 return -1;
594}
595
596/**********************************************************************/
599static void redraw_unit_info_dlg(void)
600{
601 SDL_Color bg_color = {255, 255, 255, 64};
602 struct widget *pwindow = help_dlg->end_widget_list;
603 struct units_buttons *store = (struct units_buttons *)pwindow->data.ptr;
604 SDL_Rect dst;
605
606 redraw_group(pwindow->prev, pwindow, FALSE);
607
608 dst.x = store->dock->prev->size.x - adj_size(10);
609 dst.y = store->dock->prev->size.y - adj_size(10);
610 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
611 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
612
613 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
614
615 create_frame(pwindow->dst->surface,
616 dst.x, dst.y, dst.w, dst.h,
618
619 /*------------------------------------- */
621 widget_flush(pwindow);
622}
623
624/**********************************************************************/
628{
629 SDL_Color bg_color = {255, 255, 255, 128};
630 struct widget *pwindow;
631 struct units_buttons *store;
632 struct widget *close_button = NULL;
634 struct widget *unit_button = NULL;
635 struct widget *unit_name_label = NULL;
636 struct widget *unit_info_label = NULL;
637 struct widget *requirement_label = NULL;
639 struct widget *obsolete_by_label = NULL;
641 struct widget *help_text_label = NULL;
642 struct widget *dock;
644 utf8_str *pstr;
645 SDL_Surface *surf;
646 int h, start_x, start_y, utype_count;
647 bool created, text = FALSE;
648 int scrollbar_width = 0;
649 struct unit_type *punittype;
650 char buffer[bufsz];
651 SDL_Rect area;
652 struct advance *req;
653
656 }
657
658 /* Create new dialog if it doesn't exist yet */
659 if (!help_dlg) {
660 SDL_Surface *background_tmpl, *background, *unit_name, *icon;
661 SDL_Rect dst;
662
664 created = TRUE;
665
666 /* Create dialog */
667 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
668 store = fc_calloc(1, sizeof(struct units_buttons));
669
670 /* Create window */
672 title->style |= TTF_STYLE_BOLD;
673
676 set_wstate(pwindow , FC_WS_NORMAL);
677 pwindow->data.ptr = (void *)store;
678 add_to_gui_list(ID_WINDOW, pwindow);
679
680 help_dlg->end_widget_list = pwindow;
681
682 area = pwindow->area;
683
684 /* ------------------ */
685
686 /* Close button */
687 close_button = create_themeicon(current_theme->small_cancel_icon,
688 pwindow->dst,
691 close_button->info_label
692 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
693 close_button->action = exit_help_dlg_callback;
694 set_wstate(close_button, FC_WS_NORMAL);
695 close_button->key = SDLK_ESCAPE;
696
697 add_to_gui_list(ID_BUTTON, close_button);
698
699 /* ------------------ */
700 dock = close_button;
701
702 /* --- Create scrollable unit list on the left side ---*/
703
705 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
706
707 /* Background template for entries in scroll list */
711
713 0, 0, background_tmpl->w - 1, background_tmpl->h - 1,
715
716 utype_count = 0;
718
719 /* Copy background surface */
720 background = copy_surface(background_tmpl);
721
722 /* Blit unit name */
725 dst.x = adj_size(35) + (background->w - unit_name->w - adj_size(35)) / 2;
726 dst.y = (background->h - unit_name->h) / 2;
727 alphablit(unit_name, NULL, background, &dst, 255);
729
730 /* Blit unit icon */
732 adj_size(36), adj_size(36), 1, TRUE, TRUE);
733 dst.x = (adj_size(35) - icon->w) / 2;
734 dst.y = (background->h - icon->h) / 2;
735 alphablit(icon, NULL, background, &dst, 255);
736 FREESURFACE(icon);
737
738 unit_button = create_icon2(background, pwindow->dst,
740
744
745 if (utype_count++ >= 10) {
747 }
748
750
752
756
757 if (utype_count > 10) {
760 }
761
762 /* Toggle techs list button */
764 current_theme->up_icon,
765 pwindow->dst,
766 _("Units"),
767 FONTO_DEFAULT, 0);
768#if 0
770 if (store->show_tree) {
772 }
773#endif
774
777
779
780 dock = list_toggle_button;
781 store->dock = dock;
782 } else {
783 created = FALSE;
785 pwindow = help_dlg->end_widget_list;
786 store = (struct units_buttons *)pwindow->data.ptr;
787 dock = store->dock;
788
789 area = pwindow->area;
790
791 /* Delete any previous list entries */
794 dock->prev);
796 }
797 }
798
805
809
810 {
811 char buf[2048];
812
813 fc_snprintf(buf, sizeof(buf), "%s %d %s",
815 PL_("shield", "shields", utype_build_shield_cost_base(punittype)));
816
817 if (punittype->pop_cost) {
818 cat_snprintf(buf, sizeof(buf), " %d %s",
819 punittype->pop_cost, PL_("citizen", "citizens",
820 punittype->pop_cost));
821 }
822
823 cat_snprintf(buf, sizeof(buf), " %s", _("Upkeep:"));
824
825 if (punittype->upkeep[O_SHIELD]) {
826 cat_snprintf(buf, sizeof(buf), " %d %s",
827 punittype->upkeep[O_SHIELD], PL_("shield", "shields",
828 punittype->upkeep[O_SHIELD]));
829 }
830 if (punittype->upkeep[O_FOOD]) {
831 cat_snprintf(buf, sizeof(buf), " %d %s",
832 punittype->upkeep[O_FOOD], PL_("food", "foods",
833 punittype->upkeep[O_FOOD]));
834 }
835 if (punittype->upkeep[O_GOLD]) {
836 cat_snprintf(buf, sizeof(buf), " %d %s",
837 punittype->upkeep[O_GOLD], PL_("gold", "golds",
838 punittype->upkeep[O_GOLD]));
839 }
840 if (punittype->happy_cost) {
841 cat_snprintf(buf, sizeof(buf), " %d %s",
842 punittype->happy_cost, PL_("citizen", "citizens",
843 punittype->happy_cost));
844 }
845
846 cat_snprintf(buf, sizeof(buf), "\n%s %d %s %d %s %s\n%s %d %s %d %s %d",
847 _("Attack:"), punittype->attack_strength,
848 _("Defense:"), punittype->defense_strength,
849 _("Move:"), move_points_text(punittype->move_rate, TRUE),
850 _("Vision:"), punittype->vision_radius_sq,
851 _("Firepower:"), punittype->firepower,
852 _("Hitpoints:"), punittype->hp);
853
855 FONTO_ATTENTION, 0);
859 }
860
861 /* Requirement */
863 _("Requirement:"),
864 FONTO_ATTENTION, 0);
868
870
871 if (advance_number(req) == A_NONE) {
873 Q_("?tech:None"),
874 FONTO_ATTENTION, 0);
876 } else {
878
885 requirement_label2->string_utf8->fgcol = *get_tech_color(req_id);
888 }
892
893 /* Obsolete by */
895 _("Obsolete by:"),
896 FONTO_ATTENTION, 0);
900
901 if (punittype->obsoleted_by == U_NOT_OBSOLETED) {
903 Q_("?utype:None"),
904 FONTO_ATTENTION, 0);
906 } else {
907 const struct unit_type *utype = punittype->obsoleted_by;
908 struct advance *obs_req = utype_primary_tech_req(utype);
909
915 obsolete_by_label2->string_utf8->fgcol
920 }
922 dock = obsolete_by_label2;
924
925 /* Helptext */
926 start_x = (area.x + 1 + scrollbar_width + help_dlg->active_widget_list->size.w + adj_size(20));
927
928 buffer[0] = '\0';
929 helptext_unit(buffer, sizeof(buffer), client.conn.playing, "", utype_by_number(type_id),
930 TRUE);
931 if (buffer[0] != '\0') {
933
938 text = TRUE;
939 }
940
942
943 /* --------------------------------------------------------- */
944 if (created) {
945
947 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
948 FREESURFACE(surf);
949 }
950
951 area = pwindow->area;
952
953 widget_set_position(pwindow,
954 (main_window_width() - pwindow->size.w) / 2,
955 (main_window_height() - pwindow->size.h) / 2);
956
957 /* Exit button */
958 close_button = pwindow->prev;
959 widget_set_position(close_button,
960 area.x + area.w - close_button->size.w - 1,
961 pwindow->size.y + adj_size(2));
962
963 /* List toggle button */
964 list_toggle_button = store->dock;
966
967 /* List entries */
969 area.y + list_toggle_button->size.h, 0, 0,
972
973 /* Scrollbar */
974 if (help_dlg->scroll) {
976 area.x, area.y + list_toggle_button->size.h,
977 h, FALSE);
978 }
979 }
980
981 unit_name_label = store->dock->prev;
982 widget_set_position(unit_name_label, start_x, area.y + adj_size(16));
983
984 start_y = unit_name_label->size.y + unit_name_label->size.h + adj_size(10);
985
988
989 start_y += unit_info_label->size.h;
990
993
996 requirement_label->size.x + requirement_label->size.w + adj_size(5),
997 start_y);
998
1001 requirement_label2->size.x + requirement_label2->size.w + adj_size(10),
1002 start_y);
1003
1006 obsolete_by_label->size.x + obsolete_by_label->size.w + adj_size(5),
1007 start_y);
1008
1009 start_y += obsolete_by_label2->size.h + adj_size(20);
1010
1011 if (text) {
1014 }
1015
1017}
1018
1019/* =============================================== */
1020/* ==================== Tech Tree ================ */
1021/* =============================================== */
1022
1023/**********************************************************************/
1026static int change_tech_callback(struct widget *pwidget)
1027{
1029 popup_tech_info(MAX_ID - pwidget->id);
1030 }
1031
1032 return -1;
1033}
1034
1035/**********************************************************************/
1038static int show_tech_tree_callback(struct widget *pwidget)
1039{
1041 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1042
1043 store->show_tree = !store->show_tree;
1044 if (!store->show_tree) {
1045 store->show_full_tree = FALSE;
1046 store->dock->theme2 = current_theme->up_icon;
1047 }
1048 popup_tech_info(MAX_ID - store->dock->prev->id);
1049 }
1050
1051 return -1;
1052}
1053
1054/**********************************************************************/
1057static void redraw_tech_info_dlg(void)
1058{
1059 SDL_Color bg_color = {255, 255, 255, 64};
1060 struct widget *pwindow = help_dlg->end_widget_list;
1061 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1063 utf8_str *pstr;
1064 SDL_Rect dst;
1065
1066 redraw_group(pwindow->prev, pwindow, FALSE);
1067
1068 dst.x = store->dock->prev->prev->size.x - adj_size(10);
1069 dst.y = store->dock->prev->prev->size.y - adj_size(10);
1070 dst.w = pwindow->size.w - (dst.x - pwindow->size.x) - adj_size(10);
1071 dst.h = pwindow->size.h - (dst.y - pwindow->size.y) - adj_size(10);
1072
1073 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1074
1075 create_frame(pwindow->dst->surface,
1076 dst.x, dst.y, dst.w, dst.h,
1078
1079 /* -------------------------- */
1081 pstr->style |= TTF_STYLE_BOLD;
1082
1084 dst.x = store->dock->prev->prev->size.x;
1085 if (store->targets[0]) {
1086 dst.y = store->targets[0]->size.y - text0->h;
1087 } else {
1088 dst.y = store->dock->prev->prev->size.y
1089 + store->dock->prev->prev->size.h + adj_size(10);
1090 }
1091
1092 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1094
1095 if (store->sub_targets[0]) {
1096 int i;
1097
1099
1100 copy_chars_to_utf8_str(pstr, _("( with "));
1102
1105 i = 0;
1107 dst.x = store->sub_targets[i]->size.x - text0->w;
1108 dst.y = store->sub_targets[i]->size.y;
1109
1110 alphablit(text0, NULL, pwindow->dst->surface, &dst, 255);
1111 dst.x = store->sub_targets[i]->size.x + store->sub_targets[i]->size.w;
1112 dst.y = store->sub_targets[i]->size.y;
1113
1114 alphablit(text1, NULL, pwindow->dst->surface, &dst, 255);
1115 i++;
1116 }
1117
1120 }
1122
1124 widget_flush(pwindow);
1125}
1126
1127/**********************************************************************/
1131 struct widget *pwindow,
1132 struct techs_buttons *store)
1133{
1134 struct widget *pwidget;
1135 struct widget *last, *budynki;
1136 struct widget *dock = store->dock;
1138 int start_x, start_y, imp_count, unit_count, flags_count, gov_count;
1139 char buffer[bufsz];
1140 SDL_Surface *surf;
1141
1142 start_x = (pwindow->area.x + adj_size(1) + width + help_dlg->active_widget_list->size.w + adj_size(20));
1143
1144 /* Tech tree icon */
1145 pwidget = create_icon2(current_theme->tech_tree_icon, pwindow->dst,
1147
1148 set_wstate(pwidget, FC_WS_NORMAL);
1150 pwidget->id = MAX_ID - tech;
1151 widget_add_as_prev(pwidget, dock);
1152 dock = pwidget;
1153
1154 /* Tech name (heading) */
1155 pwidget
1157 pwindow->dst,
1160
1161 pwidget->id = ID_LABEL;
1162 widget_add_as_prev(pwidget, dock);
1163 dock = pwidget;
1164
1165 /* Target techs */
1166 targets_count = 0;
1168 if ((targets_count < 6)
1169 && (advance_required(aidx, AR_ONE) == tech
1170 || advance_required(aidx, AR_TWO) == tech)) {
1171 pwidget
1176 pwidget->string_utf8->fgcol = *get_tech_color(aidx);
1177 max_width = MAX(max_width, pwidget->size.w);
1178 set_wstate(pwidget, FC_WS_NORMAL);
1179 pwidget->action = change_tech_callback;
1180 pwidget->id = MAX_ID - aidx;
1181 widget_add_as_prev(pwidget, dock);
1182 dock = pwidget;
1183 store->targets[targets_count++] = pwidget;
1184 }
1186 if (targets_count < 6) {
1187 store->targets[targets_count] = NULL;
1188 }
1189
1191 if (targets_count > 0) {
1192 int sub_tech;
1193
1194 for (i = 0; i < targets_count; i++) {
1195 sub_tech = MAX_ID - store->targets[i]->id;
1196 if (advance_required(sub_tech, AR_ONE) == tech
1199 } else if (advance_required(sub_tech, AR_TWO) == tech
1202 } else {
1203 continue;
1204 }
1205 pwidget
1211 set_wstate(pwidget, FC_WS_NORMAL);
1212 pwidget->action = change_tech_callback;
1213 pwidget->id = MAX_ID - sub_tech;
1214 widget_add_as_prev(pwidget, dock);
1215 dock = pwidget;
1216 store->sub_targets[sub_targets_count++] = pwidget;
1217 }
1218 }
1219 if (sub_targets_count < 6) {
1221 }
1222
1223 /* Fill array with iprvm. icons */
1224 budynki = pwidget;
1225
1226 /* Target governments */
1227 gov_count = 0;
1228 governments_iterate(gov) {
1229 requirement_vector_iterate(&(gov->reqs), preq) {
1230 if (VUT_ADVANCE == preq->source.kind
1231 && advance_number(preq->source.value.advance) == tech) {
1232
1233 pwidget
1235 pwindow->dst,
1239 set_wstate(pwidget, FC_WS_NORMAL);
1240 pwidget->action = change_gov_callback;
1241 pwidget->id = MAX_ID - government_index(gov);
1242 widget_add_as_prev(pwidget, dock);
1243 dock = pwidget;
1244 gov_count++;
1245 }
1248
1249 /* Target improvements */
1250 imp_count = 0;
1251 improvement_iterate(pimprove) {
1252 if (valid_improvement(pimprove)) {
1253 /* FIXME: this should show ranges and all the reqs.
1254 * Currently it's limited to 1 req. */
1255 requirement_vector_iterate(&(pimprove->reqs), preq) {
1256 if (VUT_ADVANCE == preq->source.kind
1257 && advance_number(preq->source.value.advance) == tech) {
1258 surf = get_building_surface(pimprove);
1260 resize_surface_box(surf, adj_size(48), adj_size(48), 1, TRUE,
1261 TRUE),
1262 pwindow->dst,
1266 set_wstate(pwidget, FC_WS_NORMAL);
1267 if (is_wonder(pimprove)) {
1269 }
1270 pwidget->action = change_impr_callback;
1271 pwidget->id = MAX_ID - improvement_number(pimprove);
1272 widget_add_as_prev(pwidget, dock);
1273 dock = pwidget;
1274 imp_count++;
1275 }
1276
1277 break;
1279 }
1281
1282 unit_count = 0;
1287 adj_size(48), adj_size(48), 1, TRUE, TRUE),
1290 set_wstate(pwidget, FC_WS_NORMAL);
1291 pwidget->action = change_unit_callback;
1292 pwidget->id = MAX_ID - utype_number(un);
1293 widget_add_as_prev(pwidget, dock);
1294 dock = pwidget;
1295 unit_count++;
1296 }
1298
1299 buffer[0] = '\0';
1300 if (tech != A_NONE) {
1301 helptext_advance(buffer, sizeof(buffer), client.conn.playing, "", tech);
1302 }
1303 if (buffer[0] != '\0') {
1305
1307 pwidget = create_iconlabel(NULL, pwindow->dst, pstr, 0);
1308 pwidget->id = ID_LABEL;
1309 widget_add_as_prev(pwidget, dock);
1310 flags_count = 1;
1311 } else {
1312 flags_count = 0;
1313 }
1314
1315 last = pwidget;
1316 /* --------------------------------------------- */
1317
1318 /* Tree button */
1319 pwidget = store->dock->prev;
1320 pwidget->size.x = pwindow->area.x + pwindow->area.w - pwidget->size.w - adj_size(17);
1321 pwidget->size.y = pwindow->area.y + adj_size(16);
1322
1323 /* Tech label */
1324 pwidget = pwidget->prev;
1325 pwidget->size.x = start_x;
1326 pwidget->size.y = pwindow->area.y + adj_size(16);
1327 start_y = pwidget->size.y + pwidget->size.h + adj_size(30);
1328
1329 if (targets_count) {
1330 int j = 0;
1331
1332 i = 0;
1333
1334 while (i < 6 && store->targets[i]) {
1335 store->targets[i]->size.x = pwindow->size.x + start_x;
1336 store->targets[i]->size.y = start_y;
1337
1338 if (store->sub_targets[j]) {
1339 int t0 = MAX_ID - store->targets[i]->id;
1340 int t1 = MAX_ID - store->sub_targets[j]->id;
1341
1342 if (advance_required(t0, AR_ONE) == t1
1343 || advance_required(t0, AR_TWO) == t1) {
1344 store->sub_targets[j]->size.x = pwindow->size.x + start_x + max_width + 60;
1345 store->sub_targets[j]->size.y = store->targets[i]->size.y;
1346 j++;
1347 }
1348 }
1349
1350 start_y += store->targets[i]->size.h;
1351 i++;
1352 }
1353
1354 start_y += adj_size(10);
1355 }
1356 pwidget = NULL;
1357
1358 if (gov_count) {
1359 pwidget = budynki->prev;
1360 while (gov_count-- && pwidget) {
1361 pwidget->size.x = pwindow->size.x + start_x;
1362 pwidget->size.y = start_y;
1363 start_y += pwidget->size.h + adj_size(2);
1364 pwidget = pwidget->prev;
1365 }
1366 }
1367
1368 if (imp_count) {
1369 if (!pwidget) {
1370 pwidget = budynki->prev;
1371 }
1372 while (imp_count-- && pwidget) {
1373 pwidget->size.x = pwindow->size.x + start_x;
1374 pwidget->size.y = start_y;
1375 start_y += pwidget->size.h + adj_size(2);
1376 pwidget = pwidget->prev;
1377 }
1378 }
1379
1380 if (unit_count) {
1381 if (!pwidget) {
1382 pwidget = budynki->prev;
1383 }
1384 while (unit_count-- && pwidget) {
1385 pwidget->size.x = pwindow->size.x + start_x;
1386 pwidget->size.y = start_y;
1387 start_y += pwidget->size.h + adj_size(2);
1388 pwidget = pwidget->prev;
1389 }
1390 }
1391
1392 if (flags_count) {
1393 if (!pwidget) {
1394 pwidget = budynki->prev;
1395 }
1396 while (flags_count-- && pwidget) {
1397 pwidget->size.x = pwindow->size.x + start_x;
1398 pwidget->size.y = start_y;
1399 start_y += pwidget->size.h + adj_size(2);
1400 pwidget = pwidget->prev;
1401 }
1402 }
1403
1404 return last;
1405}
1406
1407/**********************************************************************/
1410static void redraw_tech_tree_dlg(void)
1411{
1413 SDL_Color bg_color = {255, 255, 255, 64};
1414 struct widget *pwindow = help_dlg->end_widget_list;
1415 struct widget *sub0, *sub1;
1416 struct techs_buttons *store = (struct techs_buttons *)pwindow->data.ptr;
1417 struct widget *ptech = store->dock->prev;
1418 int i,j, tech, count;
1419 int step;
1420 int mod;
1421 SDL_Rect dst;
1422
1423 /* Redraw Window with exit button */
1424 redraw_group(pwindow->prev, pwindow, FALSE);
1425
1426 dst.x = pwindow->area.x + pwindow->area.w - adj_size(459) - adj_size(7);
1427 dst.y = pwindow->area.y + adj_size(6);
1428 dst.w = pwindow->area.w - (dst.x - pwindow->area.x) - adj_size(10);
1429 dst.h = pwindow->area.h - (dst.y - pwindow->area.y) - adj_size(10);
1430
1431 fill_rect_alpha(pwindow->dst->surface, &dst, &bg_color);
1432
1433 create_frame(pwindow->dst->surface,
1434 dst.x, dst.y, dst.w, dst.h,
1436
1437 /* Draw req arrows */
1438 i = 0;
1439 while (i < 4 && store->sub_req[i]) {
1440 i++;
1441 }
1442 count = i;
1443
1444 i = 0;
1445 while (i < 2 && store->requirement_button[i]) {
1446 tech = MAX_ID - store->requirement_button[i]->id;
1447
1448 /* Find sub req's */
1449 if (i) {
1450 sub0 = NULL;
1451 for (j = count - 1; j >= 0; j--) {
1452 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1453 sub0 = store->sub_req[j];
1454 break;
1455 }
1456 }
1457
1458 sub1 = NULL;
1459 for (j = count - 1; j >= 0; j--) {
1460 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1461 sub1 = store->sub_req[j];
1462 break;
1463 }
1464 }
1465 } else {
1466 sub0 = NULL;
1467 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1468 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_ONE)) {
1469 sub0 = store->sub_req[j];
1470 break;
1471 }
1472 }
1473
1474 sub1 = NULL;
1475 for (j = 0; j < 4 && store->sub_req[j]; j++) {
1476 if (MAX_ID - store->sub_req[j]->id == advance_required(tech, AR_TWO)) {
1477 sub1 = store->sub_req[j];
1478 break;
1479 }
1480 }
1481 }
1482
1483 /* Draw main Arrow */
1485 store->requirement_button[i]->size.x + store->requirement_button[i]->size.w,
1486 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1487 ptech->size.x,
1488 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1489 line_color);
1490
1491 /* Draw sub req arrows */
1492 if (sub0 || sub1) {
1494 store->requirement_button[i]->size.x - adj_size(10),
1495 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1496 store->requirement_button[i]->size.x ,
1497 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1498 line_color);
1499 }
1500
1501 if (sub0) {
1503 store->requirement_button[i]->size.x - adj_size(10),
1504 sub0->size.y + sub0->size.h / 2,
1505 store->requirement_button[i]->size.x - adj_size(10),
1506 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1507 line_color);
1509 sub0->size.x + sub0->size.w,
1510 sub0->size.y + sub0->size.h / 2,
1511 store->requirement_button[i]->size.x - adj_size(10),
1512 sub0->size.y + sub0->size.h / 2,
1513 line_color);
1514 }
1515
1516 if (sub1) {
1518 store->requirement_button[i]->size.x - adj_size(10),
1519 sub1->size.y + sub1->size.h / 2,
1520 store->requirement_button[i]->size.x - adj_size(10),
1521 store->requirement_button[i]->size.y + store->requirement_button[i]->size.h / 2,
1522 line_color);
1524 sub1->size.x + sub1->size.w,
1525 sub1->size.y + sub1->size.h / 2,
1526 store->requirement_button[i]->size.x - adj_size(10),
1527 sub1->size.y + sub1->size.h / 2,
1528 line_color);
1529 }
1530 i++;
1531 }
1532
1533 i = 0;
1534 while (i < 6 && store->targets[i]) {
1535 i++;
1536 }
1537 count = i;
1538
1539 if (count > 4) {
1540 mod = 3;
1541 } else {
1542 mod = 2;
1543 }
1544
1545 for (i = 0; i < count; i++) {
1546 tech = MAX_ID - store->targets[i]->id;
1547 step = ptech->size.h / (count + 1);
1548
1549 switch ((i % mod)) {
1550 case 2:
1552 break;
1553 case 1:
1555 break;
1556 default:
1558 break;
1559 }
1560
1561 /* Find sub reqs */
1562 if (advance_required(tech, AR_ONE) == MAX_ID - ptech->id) {
1563 sub0 = ptech;
1564 } else {
1565 sub0 = NULL;
1566 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1567 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_ONE)) {
1568 sub0 = store->sub_targets[j];
1569 break;
1570 }
1571 }
1572 }
1573
1574 if (advance_required(tech, AR_TWO) == MAX_ID - ptech->id) {
1575 sub1 = ptech;
1576 } else {
1577 sub1 = NULL;
1578 for (j = 0; j < 6 && store->sub_targets[j]; j++) {
1579 if (MAX_ID - store->sub_targets[j]->id == advance_required(tech, AR_TWO)) {
1580 sub1 = store->sub_targets[j];
1581 break;
1582 }
1583 }
1584 }
1585
1586 /* Draw sub targets arrows */
1587 if (sub0 || sub1) {
1588 create_line(store->targets[i]->dst->surface,
1589 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1590 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1591 store->targets[i]->size.x ,
1592 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1593 line_color);
1594 }
1595
1596 if (sub0) {
1597 int y;
1598
1599 if (sub0 == ptech) {
1600 y = sub0->size.y + step * (i + 1);
1601 } else {
1602 y = sub0->size.y + sub0->size.h / 2;
1603 }
1604
1605 create_line(store->targets[i]->dst->surface,
1606 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1607 y,
1608 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1609 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1610 line_color);
1611 create_line(store->targets[i]->dst->surface,
1612 sub0->size.x + sub0->size.w,
1613 y,
1614 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1615 y,
1616 line_color);
1617 }
1618
1619 if (sub1) {
1620 int y;
1621
1622 if (sub1 == ptech) {
1623 y = sub1->size.y + step * (i + 1);
1624 } else {
1625 y = sub1->size.y + sub1->size.h / 2;
1626 }
1627
1628 create_line(store->targets[i]->dst->surface,
1629 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1630 y,
1631 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1632 store->targets[i]->size.y + store->targets[i]->size.h / 2,
1633 line_color);
1634 create_line(store->targets[i]->dst->surface,
1635 sub1->size.x + sub1->size.w,
1636 y,
1637 store->targets[i]->size.x - ((i % mod) + 1) * 6,
1638 y,
1639 line_color);
1640 }
1641 }
1642
1643 /* Redraw rest */
1645
1646 widget_flush(pwindow);
1647}
1648
1649/**********************************************************************/
1653{
1655 struct techs_buttons *store = (struct techs_buttons *)help_dlg->end_widget_list->data.ptr;
1656
1657 if (store->show_full_tree) {
1658 pwidget->theme2 = current_theme->up_icon;
1659 } else {
1660 pwidget->theme2 = current_theme->down_icon;
1661 }
1662 store->show_full_tree = !store->show_full_tree;
1663 popup_tech_info(MAX_ID - store->dock->prev->id);
1664 }
1665
1666 return -1;
1667}
1668
1669/**********************************************************************/
1673 struct widget *pwindow,
1674 struct techs_buttons *store)
1675{
1677 struct widget *pwidget;
1678 struct widget *ptech;
1679 utf8_str *pstr;
1680 SDL_Surface *surf;
1681 struct widget *dock = store->dock;
1682
1684 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1685
1688 pwidget = create_icon2(surf, pwindow->dst,
1690
1691 set_wstate(pwidget, FC_WS_NORMAL);
1693 pwidget->id = MAX_ID - tech;
1694 widget_add_as_prev(pwidget, dock);
1695 ptech = pwidget;
1696 dock = pwidget;
1697
1698 req_count = 0;
1699 for (i = AR_ONE; i <= AR_TWO; i++) {
1702
1703 if (NULL != vap && A_NONE != ar) {
1706 pwidget = create_icon2(surf, pwindow->dst,
1708 set_wstate(pwidget, FC_WS_NORMAL);
1709 pwidget->action = change_tech_callback;
1710 pwidget->id = MAX_ID - ar;
1711 widget_add_as_prev(pwidget, dock);
1712 dock = pwidget;
1713 store->requirement_button[req_count++] = pwidget;
1714 }
1715 }
1716
1717 sub_req_count = 0;
1718
1719 if (store->show_full_tree && req_count > 0) {
1720 int j, sub_tech;
1721
1722 for (j = 0; j < req_count; j++) {
1723 sub_tech = MAX_ID - store->requirement_button[j]->id;
1724 for (i = AR_ONE; i <= AR_TWO; i++) {
1727
1728 if (NULL != vap && A_NONE != ar) {
1731 pwidget = create_icon2(surf, pwindow->dst,
1733 set_wstate(pwidget, FC_WS_NORMAL);
1734 pwidget->action = change_tech_callback;
1735 pwidget->id = MAX_ID - ar;
1736 widget_add_as_prev(pwidget, dock);
1737 dock = pwidget;
1738 store->sub_req[sub_req_count++] = pwidget;
1739 }
1740 }
1741 }
1742 }
1743
1744 if (sub_req_count < 4) {
1745 store->sub_req[sub_req_count] = NULL;
1746 }
1747
1748 targets_count = 0;
1750 if ((targets_count < 6)
1751 && (advance_required(aidx, AR_ONE) == tech
1752 || advance_required(aidx, AR_TWO) == tech)) {
1755 pwidget = create_icon2(surf, pwindow->dst,
1757
1758 set_wstate(pwidget, FC_WS_NORMAL);
1759 pwidget->action = change_tech_callback;
1760 pwidget->id = MAX_ID - aidx;
1761 widget_add_as_prev(pwidget, dock);
1762 dock = pwidget;
1763 store->targets[targets_count++] = pwidget;
1764 }
1766 if (targets_count < 6) {
1767 store->targets[targets_count] = NULL;
1768 }
1769
1771 if (targets_count > 0) {
1772 int sub_tech;
1773
1774 for (i = 0; i < targets_count; i++) {
1775 sub_tech = MAX_ID - store->targets[i]->id;
1776 if (advance_required(sub_tech, AR_ONE) == tech
1779 } else if (advance_required(sub_tech, AR_TWO) == tech
1782 } else {
1783 continue;
1784 }
1785
1788 pwidget = create_icon2(surf, pwindow->dst,
1790 set_wstate(pwidget, FC_WS_NORMAL);
1791 pwidget->action = change_tech_callback;
1792 pwidget->id = MAX_ID - sub_tech;
1793 widget_add_as_prev(pwidget, dock);
1794 dock = pwidget;
1795 store->sub_targets[sub_targets_count++] = pwidget;
1796 }
1797 }
1798 if (sub_targets_count < 6) {
1800 }
1801
1803
1804 /* ------------------------------------------ */
1805 if (sub_req_count > 0) {
1806 w = (adj_size(20) + store->sub_req[0]->size.w) * 2;
1807 w += (pwindow->size.w - (20 + store->sub_req[0]->size.w + w + ptech->size.w)) / 2;
1808 } else {
1809 if (req_count > 0) {
1810 w = (pwindow->area.x + 1
1811 + width + store->requirement_button[0]->size.w * 2 + adj_size(20));
1812 w += (pwindow->size.w - ((adj_size(20) + store->requirement_button[0]->size.w)
1813 + w + ptech->size.w)) / 2;
1814 } else {
1815 w = (pwindow->size.w - ptech->size.w) / 2;
1816 }
1817 }
1818
1819 ptech->size.x = pwindow->size.x + w;
1820 ptech->size.y = pwindow->area.y + (pwindow->area.h - ptech->size.h) / 2;
1821
1822 if (req_count > 0) {
1823 h = (req_count == 1 ? store->requirement_button[0]->size.h :
1824 req_count * (store->requirement_button[0]->size.h + adj_size(80)) - adj_size(80));
1825 h = ptech->size.y + (ptech->size.h - h) / 2;
1826 for (i = 0; i < req_count; i++) {
1827 store->requirement_button[i]->size.x
1828 = ptech->size.x - adj_size(20) - store->requirement_button[i]->size.w;
1829 store->requirement_button[i]->size.y = h;
1830 h += (store->requirement_button[i]->size.h + adj_size(80));
1831 }
1832 }
1833
1834 if (sub_req_count > 0) {
1835 h = (sub_req_count == 1 ? store->sub_req[0]->size.h :
1836 sub_req_count * (store->sub_req[0]->size.h + adj_size(20)) - adj_size(20));
1837 h = ptech->size.y + (ptech->size.h - h) / 2;
1838 for (i = 0; i < sub_req_count; i++) {
1839 store->sub_req[i]->size.x
1840 = ptech->size.x - (adj_size(20) + store->sub_req[i]->size.w) * 2;
1841 store->sub_req[i]->size.y = h;
1842 h += (store->sub_req[i]->size.h + adj_size(20));
1843 }
1844 }
1845
1846 if (targets_count > 0) {
1847 h = (targets_count == 1 ? store->targets[0]->size.h :
1848 targets_count * (store->targets[0]->size.h + adj_size(20)) - adj_size(20));
1849 h = ptech->size.y + (ptech->size.h - h) / 2;
1850 for (i = 0; i < targets_count; i++) {
1851 store->targets[i]->size.x = ptech->size.x + ptech->size.w + adj_size(20);
1852 store->targets[i]->size.y = h;
1853 h += (store->targets[i]->size.h + adj_size(20));
1854 }
1855 }
1856
1857 if (sub_targets_count > 0) {
1858 if (sub_targets_count < 3) {
1859 store->sub_targets[0]->size.x
1860 = ptech->size.x + ptech->size.w - store->sub_targets[0]->size.w;
1861 store->sub_targets[0]->size.y
1862 = ptech->size.y - store->sub_targets[0]->size.h - adj_size(10);
1863 if (store->sub_targets[1]) {
1864 store->sub_targets[1]->size.x
1865 = ptech->size.x + ptech->size.w - store->sub_targets[1]->size.w;
1866 store->sub_targets[1]->size.y = ptech->size.y + ptech->size.h + adj_size(10);
1867 }
1868 } else {
1869 if (sub_targets_count < 5) {
1870 for (i = 0; i < MIN(sub_targets_count, 4); i++) {
1871 store->sub_targets[i]->size.x
1872 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1873 if (i < 2) {
1874 store->sub_targets[i]->size.y
1875 = ptech->size.y - (store->sub_targets[i]->size.h + adj_size(5)) * (2 - i);
1876 } else {
1877 store->sub_targets[i]->size.y
1878 = ptech->size.y + ptech->size.h + adj_size(5)
1879 + (store->sub_targets[i]->size.h + adj_size(5)) * (i - 2);
1880 }
1881 }
1882 } else {
1883 h = (store->sub_targets[0]->size.h + adj_size(6));
1884 for (i = 0; i < MIN(sub_targets_count, 6); i++) {
1885 switch (i) {
1886 case 0:
1887 store->sub_targets[i]->size.x
1888 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1889 store->sub_targets[i]->size.y = ptech->size.y - h * 2;
1890 break;
1891 case 1:
1892 store->sub_targets[i]->size.x
1893 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1894 - adj_size(10);
1895 store->sub_targets[i]->size.y = ptech->size.y - h - h / 2;
1896 break;
1897 case 2:
1898 store->sub_targets[i]->size.x
1899 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w;
1900 store->sub_targets[i]->size.y = ptech->size.y - h;
1901 break;
1902 case 3:
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 + ptech->size.h + adj_size(6);
1906 break;
1907 case 4:
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) + h;
1911 break;
1912 default:
1913 store->sub_targets[i]->size.x
1914 = ptech->size.x + ptech->size.w - store->sub_targets[i]->size.w * 2
1915 - adj_size(10);
1916 store->sub_targets[i]->size.y
1917 = ptech->size.y + ptech->size.h + adj_size(6) + h / 2 ;
1918 break;
1919 }
1920 }
1921 }
1922 }
1923 }
1924
1925 return pwidget;
1926}
1927
1928/**********************************************************************/
1932{
1933 struct widget *pwindow;
1934 struct techs_buttons *store;
1935 struct widget *close_button = NULL;
1936 struct widget *advance_label = NULL;
1937 struct widget *list_toggle_button = NULL;
1938 struct widget *dock;
1939 utf8_str *title;
1940 utf8_str *pstr;
1941 SDL_Surface *surf;
1942 int h, tech_count;
1943 bool created;
1944 int scrollbar_width = 0;
1945 SDL_Rect area;
1946
1947 if (current_help_dlg != HELP_TECH) {
1949 }
1950
1951 /* Create new dialog if it doesn't exist yet */
1952 if (!help_dlg) {
1954 created = TRUE;
1955
1956 /* Create dialog */
1957 help_dlg = fc_calloc(1, sizeof(struct advanced_dialog));
1958 store = fc_calloc(1, sizeof(struct techs_buttons));
1959
1960 store->show_tree = FALSE;
1961 store->show_full_tree = FALSE;
1962
1963 /* Create window */
1964 title = create_utf8_from_char_fonto(_("Help : Advances Tree"),
1966 title->style |= TTF_STYLE_BOLD;
1967
1969 pwindow->data.ptr = (void *)store;
1971 set_wstate(pwindow, FC_WS_NORMAL);
1972
1973 add_to_gui_list(ID_WINDOW, pwindow);
1974
1975 help_dlg->end_widget_list = pwindow;
1976
1977 /* ------------------ */
1978
1979 /* Close button */
1980 close_button = create_themeicon(current_theme->small_cancel_icon, pwindow->dst,
1983 close_button->info_label
1984 = create_utf8_from_char_fonto(_("Close Dialog (Esc)"), FONTO_ATTENTION);
1985 close_button->action = exit_help_dlg_callback;
1986 set_wstate(close_button, FC_WS_NORMAL);
1987 close_button->key = SDLK_ESCAPE;
1988
1989 add_to_gui_list(ID_BUTTON, close_button);
1990
1991 /* ------------------ */
1992 dock = close_button;
1993
1994 /* --- Create scrollable advance list on the left side ---*/
1996 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
1997
1998 tech_count = 0;
2001
2002 if (vap) {
2005 advance_label = create_icon2(surf, pwindow->dst,
2007
2011
2012 if (tech_count++ >= 10) {
2014 }
2015 }
2017
2019
2023
2024 if (tech_count > 10) {
2027 }
2028
2029 /* Toggle techs list button */
2031 current_theme->up_icon,
2032 pwindow->dst,
2033 _("Advances"),
2034 FONTO_DEFAULT, 0);
2036 if (store->show_tree) {
2038 }
2041
2043
2044 dock = list_toggle_button;
2045 store->dock = dock;
2046 } else {
2047 created = FALSE;
2049 pwindow = help_dlg->end_widget_list;
2050 store = (struct techs_buttons *)pwindow->data.ptr;
2051 dock = store->dock;
2052
2053 /* Delete any previous list entries */
2057 }
2058
2059 /* Show/hide techs list */
2061
2062 if (store->show_tree) {
2064 } else {
2066 }
2067
2068 if (store->show_full_tree) {
2069 /* All entries are visible without scrolling */
2073 } else {
2074 int count = help_dlg->scroll->active;
2075
2077 while (advance_label->prev != NULL && --count > 0) {
2079 }
2082 }
2083 }
2084
2085 /* --------------------------------------------------------- */
2086 if (created) {
2087
2089 if (resize_window(pwindow, surf, NULL, adj_size(640), adj_size(480))) {
2090 FREESURFACE(surf);
2091 }
2092
2093 area = pwindow->area;
2094
2095 widget_set_position(pwindow,
2096 (main_window_width() - pwindow->size.w) / 2,
2097 (main_window_height() - pwindow->size.h) / 2);
2098
2099 /* Exit button */
2100 close_button = pwindow->prev;
2101 widget_set_position(close_button,
2102 area.x + area.w - close_button->size.w - 1,
2103 pwindow->size.y + adj_size(2));
2104
2105 /* List toggle button */
2106 list_toggle_button = store->dock;
2107 widget_set_position(list_toggle_button, area.x, area.y);
2108
2109 /* List entries */
2111 area.y + list_toggle_button->size.h, 0, 0,
2114 /* Scrollbar */
2115 if (help_dlg->scroll) {
2117 area.x, area.y + list_toggle_button->size.h,
2118 h, FALSE);
2119 }
2120 }
2121
2122 if (store->show_tree) {
2125 } else {
2128 }
2129}
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:76
QString current_theme
Definition fc_client.cpp:64
int Tech_type_id
Definition fc_types.h:236
int Impr_type_id
Definition fc_types.h:235
int Unit_type_id
Definition fc_types.h:241
@ 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:152
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:1381
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:1350
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:1933
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:1040
enum help_page_type current_help_dlg
Definition helpdlg.c:68
static void redraw_tech_info_dlg(void)
Definition helpdlg.c:1059
static void redraw_unit_info_dlg(void)
Definition helpdlg.c:602
static int change_tech_callback(struct widget *pwidget)
Definition helpdlg.c:1028
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:1132
void popup_impr_info(Impr_type_id impr)
Definition helpdlg.c:202
static void redraw_tech_tree_dlg(void)
Definition helpdlg.c:1412
static int help_dlg_window_callback(struct widget *pwindow)
Definition helpdlg.c:122
static int change_unit_callback(struct widget *pwidget)
Definition helpdlg.c:590
void popup_unit_info(Unit_type_id type_id)
Definition helpdlg.c:630
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:1654
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:87
@ COLOR_THEME_HELPDLG_TEXT
Definition themecolors.h:91
@ COLOR_THEME_HELPDLG_LINE3
Definition themecolors.h:90
@ COLOR_THEME_CITYDLG_LUX
Definition themecolors.h:60
@ COLOR_THEME_HELPDLG_LINE
Definition themecolors.h:88
@ COLOR_THEME_HELPDLG_LINE2
Definition themecolors.h:89
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:3294
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:116
#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:1016
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:536
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::@223 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:960
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
#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:300
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:244
@ AR_TWO
Definition tech.h:107
@ AR_ONE
Definition tech.h:106
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_index_iterate(_start, _index)
Definition tech.h:240
bool is_tech_req_for_utype(const struct unit_type *ptype, struct advance *padv)
Definition unittype.c:2730
int utype_build_shield_cost_base(const struct unit_type *punittype)
Definition unittype.c:1474
struct advance * utype_primary_tech_req(const struct unit_type *ptype)
Definition unittype.c:2716
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:1566
#define unit_type_iterate(_p)
Definition unittype.h:862
#define unit_type_iterate_end
Definition unittype.h:869
#define U_NOT_OBSOLETED
Definition unittype.h:535