Freeciv-3.2
Loading...
Searching...
No Matches
citydlg.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#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include <gtk/gtk.h>
23#include <gdk/gdk.h>
24
25/* utility */
26#include "bitvector.h"
27#include "fcintl.h"
28#include "log.h"
29#include "mem.h"
30#include "shared.h"
31#include "support.h"
32
33/* common */
34#include "city.h"
35#include "counters.h"
36#include "game.h"
37#include "map.h"
38#include "movement.h"
39#include "packets.h"
40#include "player.h"
41#include "unitlist.h"
42
43/* client */
44#include "chatline_common.h"
45#include "client_main.h"
46#include "colors.h"
47#include "control.h"
48#include "climap.h"
49#include "options.h"
50#include "text.h"
51#include "tilespec.h"
52
53/* client/agents */
54#include "cma_fec.h"
55
56/* client/gui-gtk-4.0 */
57#include "choice_dialog.h"
58#include "citizensinfo.h"
59#include "cityrep.h"
60#include "cma_fe.h"
61#include "dialogs.h"
62#include "graphics.h"
63#include "gui_main.h"
64#include "gui_stuff.h"
65#include "happiness.h"
66#include "helpdlg.h"
67#include "inputdlg.h"
68#include "mapview.h"
69#include "repodlgs.h"
70#include "wldlg.h"
71
72#include "citydlg.h"
73
74#define CITYMAP_WIDTH MIN(512, canvas_width)
75#define CITYMAP_HEIGHT (CITYMAP_WIDTH * canvas_height / canvas_width)
76#define CITYMAP_SCALE ((double)CITYMAP_WIDTH / (double)canvas_width)
77
78#define TINYSCREEN_MAX_HEIGHT (500 - 1)
79
80/* Only CDLGR_UNITS button currently uses these, others have
81 * direct callback. */
83
84struct city_dialog;
85
86/* get 'struct dialog_list' and related function */
87#define SPECLIST_TAG dialog
88#define SPECLIST_TYPE struct city_dialog
89#include "speclist.h"
90
91#define dialog_list_iterate(dialoglist, pdialog) \
92 TYPED_LIST_ITERATE(struct city_dialog, dialoglist, pdialog)
93#define dialog_list_iterate_end LIST_ITERATE_END
94
95struct unit_node {
98 int height;
102};
103
104/* get 'struct unit_node' and related function */
105#define SPECVEC_TAG unit_node
106#define SPECVEC_TYPE struct unit_node
107#include "specvec.h"
108
109#define unit_node_vector_iterate(list, elt) \
110 TYPED_VECTOR_ITERATE(struct unit_node, list, elt)
111#define unit_node_vector_iterate_end VECTOR_ITERATE_END
112
113#define NUM_CITIZENS_SHOWN 30
114
117 NUM_PAGES /* the number of pages in city dialog notebook
118 * must match the entries in misc_whichtab_label[] */
120
121enum {
126 NUM_INFO_FIELDS /* number of fields in city_info panel
127 * must match entries in output_label[] */
129
130/* minimal size for the city map scrolling windows*/
131#define CITY_MAP_MIN_SIZE_X 200
132#define CITY_MAP_MIN_SIZE_Y 150
133
134struct city_map_canvas {
135 GtkWidget *sw;
137};
138
139struct city_dialog {
140 struct city *pcity;
141
146
150
151 struct {
153
154 GtkWidget *production_bar;
155 GtkWidget *production_combo;
156 GtkWidget *buy_command;
157 GtkWidget *improvement_list;
158
159 GtkWidget *supported_units_frame;
160 GtkWidget *supported_unit_table;
161
162 GtkWidget *present_units_frame;
163 GtkWidget *present_unit_table;
164
165 struct unit_node_vector supported_units;
166 struct unit_node_vector present_units;
167
169
170 GtkListStore *change_production_store;
172
173 struct {
174 GtkWidget *production_label;
175 GtkWidget *production_bar;
176 GtkWidget *buy_command;
179
180 struct {
182
187
188 struct {
192
193 struct cma_dialog *cma_editor;
194
195 struct {
196 GtkWidget *rename_command;
197 GtkWidget *new_citizens_radio[3];
198 GtkWidget *disband_on_settler;
199 GtkWidget *whichtab_radio[NUM_PAGES];
200 short block_signal;
202
206
210
212
213 int cwidth;
214};
215
221
223
224static struct
225{
226 struct city *owner;
227 struct tile *loc;
229
230static bool low_citydlg;
231
232/****************************************/
233
234static void initialize_city_dialogs(void);
235static void city_dialog_map_create(struct city_dialog *pdialog,
238
239static struct city_dialog *get_city_dialog(struct city *pcity);
243 GdkModifierType state,
244 gpointer data);
245
246static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
248static void create_and_append_overview_page(struct city_dialog *pdialog);
249static void create_and_append_map_page(struct city_dialog *pdialog);
250static void create_and_append_buildings_page(struct city_dialog *pdialog);
251static void create_and_append_worklist_page(struct city_dialog *pdialog);
252static void create_and_append_happiness_page(struct city_dialog *pdialog);
253static void create_and_append_cma_page(struct city_dialog *pdialog);
254static void create_and_append_settings_page(struct city_dialog *pdialog);
255
256static struct city_dialog *create_city_dialog(struct city *pcity);
257
258static void city_dialog_update_title(struct city_dialog *pdialog);
259static void city_dialog_update_citizens(struct city_dialog *pdialog);
260static void city_dialog_update_counters(struct city_dialog *pdialog);
262 struct city_dialog *pdialog);
263static void city_dialog_update_map(struct city_dialog *pdialog);
264static void city_dialog_update_building(struct city_dialog *pdialog);
266 *pdialog);
268 *pdialog);
269static void city_dialog_update_present_units(struct city_dialog *pdialog);
270static void city_dialog_update_prev_next(void);
271
272static void show_units_response(void *data);
273
275 double x, double y, gpointer data);
277 double x, double y, gpointer data);
279 double x, double y, gpointer data);
281 double x, double y, gpointer data);
283 double x, double y, gpointer data);
284
285static void close_citydlg_unit_popover(struct city_dialog *pdialog);
286
287static void unit_center_callback(GSimpleAction *action, GVariant *parameter,
288 gpointer data);
289static void unit_activate_callback(GSimpleAction *action, GVariant *parameter,
290 gpointer data);
292 GVariant *parameter,
293 gpointer data);
295 GVariant *parameter,
296 gpointer data);
297static void unit_load_callback(GSimpleAction *action, GVariant *parameter,
298 gpointer data);
299static void unit_unload_callback(GSimpleAction *action, GVariant *parameter,
300 gpointer data);
301static void unit_sentry_callback(GSimpleAction *action, GVariant *parameter,
302 gpointer data);
303static void unit_fortify_callback(GSimpleAction *action, GVariant *parameter,
304 gpointer data);
305static void unit_disband_callback(GSimpleAction *action, GVariant *parameter,
306 gpointer data);
307static void unit_homecity_callback(GSimpleAction *action, GVariant *parameter,
308 gpointer data);
309static void unit_upgrade_callback(GSimpleAction *action, GVariant *parameter,
310 gpointer data);
312 double x, double y, gpointer data);
314 double x, double y, gpointer data);
316 double x, double y, gpointer data);
317static void draw_map_canvas(struct city_dialog *pdialog);
318
319static void buy_callback(GtkWidget * w, gpointer data);
320static void change_production_callback(GtkComboBox *combo,
321 struct city_dialog *pdialog);
322
323static void sell_callback(struct impr_type *pimprove, gpointer data);
324static void sell_callback_response(GtkWidget *w, gint response, gpointer data);
325
326static void impr_callback(GtkTreeView *view, GtkTreePath *path,
328
329static void rename_callback(GtkWidget * w, gpointer data);
330static void rename_popup_callback(gpointer data, gint response,
331 const char *input);
332static void set_cityopt_values(struct city_dialog *pdialog);
333static void cityopt_callback(GtkWidget * w, gpointer data);
334static void misc_whichtab_callback(GtkWidget * w, gpointer data);
335
336static void city_destroy_callback(GtkWidget *w, gpointer data);
337static void close_city_dialog(struct city_dialog *pdialog);
338static void citydlg_response_callback(GtkDialog *dlg, gint response,
339 void *data);
340static void close_callback(GtkWidget *w, gpointer data);
341static void switch_city_callback(GtkWidget *w, gpointer data);
342
343/***********************************************************************/
352
353/***********************************************************************/
356static void initialize_city_dialogs(void)
357{
358 int height;
359
361
365
366 /* Use default layout when height cannot be determined
367 * (when height == 0) */
368 if (height > 0 && height <= TINYSCREEN_MAX_HEIGHT) {
370 } else {
372 }
373
375}
376
377/***********************************************************************/
381{
383 return;
384 }
385
387
389 /* There's no reasonable way to resize a GtkImage, so we don't try.
390 Instead we just redraw the overview within the existing area. The
391 player has to close and reopen the dialog to fix this. */
392 city_dialog_update_map(pdialog);
394
396}
397
398/***********************************************************************/
402static struct city_dialog *get_city_dialog(struct city *pcity)
403{
406 }
407
409 if (pdialog->pcity == pcity) {
410 return pdialog;
411 }
413
414 return NULL;
415}
416
417/***********************************************************************/
421 int width, int height, gpointer data)
422{
423 struct city_dialog *pdialog = data;
424
427 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
428 cairo_paint_with_alpha(cr, 0.5);
429 } else {
430 cairo_paint(cr);
431 }
432}
433
434/***********************************************************************/
437static void city_dialog_map_create(struct city_dialog *pdialog,
439{
440 GtkWidget *sw, *darea;
443
452
453 darea = gtk_drawing_area_new();
456 canvas_draw_cb, pdialog, NULL);
457
459 g_signal_connect(controller, "pressed",
465 g_signal_connect(controller, "pressed",
469
470 /* save all widgets for the city map */
471 cmap_canvas->sw = sw;
472 cmap_canvas->darea = darea;
473}
474
475/***********************************************************************/
499
500/***********************************************************************/
504{
505 struct city_dialog *pdialog = get_city_dialog(pcity);
506
507 log_debug("CITYMAP_WIDTH: %d", CITYMAP_WIDTH);
508 log_debug("CITYMAP_HEIGHT: %d", CITYMAP_HEIGHT);
509 log_debug("CITYMAP_SCALE: %.3f", CITYMAP_SCALE);
510
514 }
515
516 if (!pdialog) {
517 return;
518 }
519
524 city_dialog_update_map(pdialog);
529
532
534
535 if (!low_citydlg) {
537 }
541 }
542
543 if (!client_is_observer()) {
545 }
546
550 } else {
551 /* Set the buttons we do not want live while a Diplomat investigates */
553 }
554}
555
556/***********************************************************************/
561{
562 struct city *pcity_sup, *pcity_pre;
563 struct city_dialog *pdialog;
564
567
568 if (pcity_sup && (pdialog = get_city_dialog(pcity_sup))) {
570 }
571
572 if (pcity_pre && (pdialog = get_city_dialog(pcity_pre))) {
574 }
575}
576
577/***********************************************************************/
581{
582 struct city_dialog *pdialog;
583
584 if (!(pdialog = get_city_dialog(pcity))) {
585 pdialog = create_city_dialog(pcity);
586 }
587
589
590 /* center the city map(s); this must be *after* the city dialog was drawn
591 * else the size information is missing! */
593 if (pdialog->happiness.map_canvas.sw) {
595 }
596}
597
598/***********************************************************************/
602{
603 return get_city_dialog(pcity) != NULL;
604}
605
606/***********************************************************************/
610{
611 struct city_dialog *pdialog = get_city_dialog(pcity);
612
613 if (pdialog) {
614 close_city_dialog(pdialog);
615 }
616}
617
618/***********************************************************************/
634
635/***********************************************************************/
641 GdkModifierType state,
642 gpointer data)
643{
644 struct city_dialog *pdialog = (struct city_dialog *)data;
645
646 if (state & GDK_CONTROL_MASK) {
647 switch (keyval) {
648 case GDK_KEY_Left:
650 return TRUE;
651
652 case GDK_KEY_Right:
654 return TRUE;
655
656 default:
657 break;
658 }
659 }
660
661 return FALSE;
662}
663
664/**********************************************************************/
668{
670}
671
672/***********************************************************************/
676 double x, double y, gpointer data)
677{
679 struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
680 GtkWidget *p, *label;
681 char buf[1024];
682
683 switch (GPOINTER_TO_UINT(data)) {
684 case INFO_SIZE:
685 fc_snprintf(buf, sizeof(buf), _("Population: %d, Specialists: %d"),
686 pdialog->pcity->size, city_specialists(pdialog->pcity));
687 break;
688 case INFO_FOOD:
689 get_city_dialog_output_text(pdialog->pcity, O_FOOD, buf, sizeof(buf));
690 break;
691 case INFO_SHIELD:
693 buf, sizeof(buf));
694 break;
695 case INFO_TRADE:
696 get_city_dialog_output_text(pdialog->pcity, O_TRADE, buf, sizeof(buf));
697 break;
698 case INFO_GOLD:
699 get_city_dialog_output_text(pdialog->pcity, O_GOLD, buf, sizeof(buf));
700 break;
701 case INFO_SCIENCE:
703 buf, sizeof(buf));
704 break;
705 case INFO_LUXURY:
707 buf, sizeof(buf));
708 break;
709 case INFO_CULTURE:
710 get_city_dialog_culture_text(pdialog->pcity, buf, sizeof(buf));
711 break;
712 case INFO_POLLUTION:
713 get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
714 break;
715 case INFO_ILLNESS:
716 get_city_dialog_illness_text(pdialog->pcity, buf, sizeof(buf));
717 break;
718 case INFO_AIRLIFT:
719 get_city_dialog_airlift_text(pdialog->pcity, buf, sizeof(buf));
720 break;
721 default:
722 return TRUE;
723 }
724
725 p = gtk_popover_new();
726
728
729 label = gtk_label_new(buf);
730 gtk_widget_set_name(label, "city_label");
735
737
738 g_signal_connect(p, "closed",
740
742
743 return TRUE;
744}
745
746/***********************************************************************/
752{
753 int i;
754 GtkWidget *table, *label;
755
756 static const char *output_label[NUM_INFO_FIELDS] = {
757 N_("Size:"),
758 N_("Food:"),
759 N_("Prod:"),
760 N_("Trade:"),
761 N_("Gold:"),
762 N_("Luxury:"),
763 N_("Science:"),
764 N_("Granary:"),
765 N_("Change in:"),
766 N_("Corruption:"),
767 N_("Waste:"),
768 N_("Culture:"),
769 N_("Pollution:"),
770 N_("Plague risk:"),
771 N_("Tech Stolen:"),
772 N_("Airlift:"),
773 };
774 static bool output_label_done;
776
782
784
785 for (i = 0; i < NUM_INFO_FIELDS; i++) {
786 label = gtk_label_new(output_label[i]);
787 switch (i) {
788 case INFO_SIZE:
789 case INFO_TRADE:
790 case INFO_SCIENCE:
791 case INFO_GROWTH:
793 break;
794
795 case INFO_FOOD:
796 case INFO_GOLD:
797 case INFO_GRANARY:
798 case INFO_CORRUPTION:
800 break;
801 default:
802 break;
803 }
805 gtk_widget_set_name(label, "city_label"); /* for font style? */
808 gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
809
810 label = gtk_label_new("");
811 switch (i) {
812 case INFO_TRADE:
813 case INFO_SCIENCE:
814 case INFO_GROWTH:
816 break;
817
818 case INFO_GOLD:
819 case INFO_GRANARY:
820 case INFO_CORRUPTION:
822 break;
823 default:
824 break;
825 }
826
827 g_object_set_data(G_OBJECT(label), "pdialog", pdialog);
828
830 g_signal_connect(controller, "pressed",
833
834 info_label[i] = label;
835 gtk_widget_set_name(label, "city_label"); /* ditto */
838
839 gtk_grid_attach(GTK_GRID(table), label, 1, i, 1, 1);
840 }
841
842 /*
843 * Allow special highlighting of emergencies for granary etc by
844 * city_dialog_update_information().
845 */
846 {
847 /* This will persist, and can be shared between overview and happiness
848 * pages. */
850
851 if (emergency_provider == NULL) {
853
855 ".emergency {\n"
856 " color: rgba(255, 0.0, 0.0, 255);\n"
857 "}",
858 -1);
859
864 }
865 }
866
868
869 return table;
870}
871
872/***********************************************************************/
877static void create_citydlg_main_map(struct city_dialog *pdialog,
878 GtkWidget *grid, int col, int row)
879{
880 GtkWidget *frame;
881
882 frame = gtk_frame_new(_("City map"));
885 gtk_grid_attach(GTK_GRID(grid), frame, col, row, 1, 1);
886
887 city_dialog_map_create(pdialog, &pdialog->overview.map_canvas);
889}
890
891/***********************************************************************/
895{
897 GtkListStore *store;
899
900 /* improvements */
901 /* gtk list store columns: 0 - sell value, 1 - sprite,
902 2 - description, 3 - upkeep, 4 - is redundant, 5 - tooltip */
906
910 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
911 g_object_unref(store);
913 gtk_widget_set_name(view, "small_font");
914 pdialog->overview.improvement_list = view;
915
918 rend, "pixbuf", 1, NULL);
921 rend, "text", 2,
922 "strikethrough", 4, NULL);
924 g_object_set(rend, "xalign", 1.0, NULL);
926 rend, "text", 3,
927 "strikethrough", 4, NULL);
928
930
932 pdialog);
933
934 return view;
935}
936
937/***********************************************************************/
954{
956 GtkWidget *right, *frame, *table;
957 GtkWidget *label, *sw, *view, *bar, *production_combo;
958 GtkWidget *vp;
961 /* TRANS: Overview tab in city dialog */
962 const char *tab_title = _("_Overview");
964 int page_row = 0;
965
966 /* Main page */
967 page = gtk_grid_new();
976
977 if (!low_citydlg) {
978 GtkWidget *middle;
979 GtkWidget *vbox;
981 int middle_col = 0;
982
983 /* Middle: city map, improvements */
984 middle = gtk_grid_new();
986 gtk_grid_attach(GTK_GRID(page), middle, 0, page_row++, 1, 1);
987
988 /* City map */
989 create_citydlg_main_map(pdialog, middle, middle_col++, 0);
990
991 /* Improvements */
993 gtk_grid_attach(GTK_GRID(middle), vbox, middle_col++, 0, 1, 1);
994
996
997 label = g_object_new(GTK_TYPE_LABEL, "label", _("Production:"),
998 "xalign", 0.0, "yalign", 0.5, NULL);
999 gtk_box_append(GTK_BOX(vbox), label);
1000
1002 gtk_box_append(GTK_BOX(vbox), hbox);
1003
1007
1008 bar = gtk_progress_bar_new();
1010 pdialog->overview.production_bar = bar;
1012
1013 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1014
1024
1029 rend, "pixbuf", 0, NULL);
1030 g_object_set(rend, "xalign", 0.0, NULL);
1031
1035 rend, "text", 1, "strikethrough", 3, NULL);
1036
1037 pdialog->overview.buy_command
1038 = icon_label_button_new("system-run", _("_Buy"));
1040 g_signal_connect(pdialog->overview.buy_command, "clicked",
1041 G_CALLBACK(buy_callback), pdialog);
1042
1043 label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
1044 "mnemonic-widget", view,
1045 "label", _("I_mprovements:"),
1046 "xalign", 0.0, "yalign", 0.5, NULL);
1047 gtk_box_append(GTK_BOX(vbox), label);
1048
1053 gtk_box_append(GTK_BOX(vbox), sw);
1054
1056 } else {
1057 pdialog->overview.buy_command = NULL;
1058 pdialog->overview.production_bar = NULL;
1059 pdialog->overview.production_combo = NULL;
1061 }
1062
1063 /* Bottom: info, units */
1066
1067 /* Info */
1068 frame = gtk_frame_new(_("Info"));
1069 gtk_box_append(GTK_BOX(bottom), frame);
1070
1071 table = create_city_info_table(pdialog,
1072 pdialog->overview.info_label);
1076
1077 /* Right: present and supported units (overview page) */
1079 gtk_box_append(GTK_BOX(bottom), right);
1080
1085
1086 /* Supported units */
1093 sw);
1094
1095
1102
1105
1106 /* Present units */
1113
1120
1123
1124 /* Show page */
1126}
1127
1128/***********************************************************************/
1131static void create_and_append_map_page(struct city_dialog *pdialog)
1132{
1133 if (low_citydlg) {
1134 GtkWidget *page;
1135 GtkWidget *label;
1136 const char *tab_title = _("Citymap");
1137 int page_row = 0;
1138
1139 page = gtk_grid_new();
1148
1149 create_citydlg_main_map(pdialog, page, 0, page_row++);
1150
1152 }
1153}
1154
1155/***********************************************************************/
1159 const GValue *value,
1160 double x, double y, gpointer data)
1161{
1162 struct city_dialog *pdialog = (struct city_dialog *) data;
1163 cid id;
1164 struct universal univ;
1165
1166 if (NULL != client.conn.playing
1167 && city_owner(pdialog->pcity) != client.conn.playing) {
1168 return FALSE;
1169 }
1170
1171 id = g_value_get_int(value);
1172 univ = cid_production(id);
1173
1174 city_change_production(pdialog->pcity, &univ);
1175
1176 return TRUE;
1177}
1178
1179/***********************************************************************/
1183static int create_production_header(struct city_dialog *pdialog,
1184 GtkWidget *grid, int row)
1185{
1186 GtkWidget *hgrid, *bar;
1187 int grid_col = 0;
1188
1189 hgrid = gtk_grid_new();
1195 gtk_grid_attach(GTK_GRID(grid), hgrid, 0, row++, 1, 1);
1196
1197 /* The label is set in city_dialog_update_building() */
1198 bar = gtk_progress_bar_new();
1201 pdialog->production.production_bar = bar;
1202 gtk_grid_attach(GTK_GRID(hgrid), bar, grid_col++, 0, 1, 1);
1203 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1204
1206
1207 pdialog->production.buy_command
1208 = icon_label_button_new("system-run", _("_Buy"));
1210 grid_col++, 0, 1, 1);
1211
1212 g_signal_connect(pdialog->production.buy_command, "clicked",
1213 G_CALLBACK(buy_callback), pdialog);
1214
1215 return row;
1216}
1217
1218/***********************************************************************/
1222{
1223 if (low_citydlg) {
1224 GtkWidget *page;
1225 GtkWidget *label;
1226 GtkWidget *vbox;
1227 GtkWidget *view;
1228 const char *tab_title = _("Buildings");
1229 int page_row = 0;
1230
1231 page = gtk_grid_new();
1239
1240 page_row = create_production_header(pdialog, page, page_row);
1241 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1242
1244 gtk_grid_attach(GTK_GRID(page), vbox, 0, page_row++, 1, 1);
1245
1247
1248 gtk_box_append(GTK_BOX(vbox), view);
1249
1251 }
1252}
1253
1254/***********************************************************************/
1258{
1259 const char *tab_title = _("P_roduction");
1261 GtkWidget *page, *editor;
1262 int page_row = 0;
1263
1264 page = gtk_grid_new();
1271 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1272
1273 /* Stuff that's being currently built */
1274 if (!low_citydlg) {
1276 "label", _("Production:"),
1277 "xalign", 0.0, "yalign", 0.5, NULL);
1278 pdialog->production.production_label = label;
1279 gtk_grid_attach(GTK_GRID(page), label, 0, page_row++, 1, 1);
1280
1281 page_row = create_production_header(pdialog, page, page_row);
1282 } else {
1283 pdialog->production.production_label = NULL;
1284 }
1285
1291 reset_city_worklist(editor, pdialog->pcity);
1292 gtk_grid_attach(GTK_GRID(page), editor, 0, page_row++, 1, 1);
1293 pdialog->production.worklist = editor;
1294
1296}
1297
1298/***********************************************************************/
1309{
1310 GtkWidget *page, *label, *table, *right, *left, *frame;
1311 const char *tab_title = _("Happ_iness");
1312 int page_col = 0;
1313 int left_row = 0;
1314
1315 /* Main page */
1316 page = gtk_grid_new();
1323 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1324
1325 /* Left: info, citizens */
1326 left = gtk_grid_new();
1329 gtk_grid_attach(GTK_GRID(page), left, page_col++, 0, 1, 1);
1330
1331 if (!low_citydlg) {
1332 /* Upper left: info */
1333 frame = gtk_frame_new(_("Info"));
1334 gtk_grid_attach(GTK_GRID(left), frame, 0, left_row++, 1, 1);
1335
1336 table = create_city_info_table(pdialog,
1337 pdialog->happiness.info_label);
1340 }
1341
1342 /* Lower left: citizens */
1346 0, left_row++, 1, 1);
1348 citizens_dialog_display(pdialog->pcity));
1349 }
1350
1351 /* Right: city map, happiness */
1353 gtk_grid_attach(GTK_GRID(page), right, page_col++, 0, 1, 1);
1354
1355 if (!low_citydlg) {
1356 /* Upper right: city map */
1357 frame = gtk_frame_new(_("City map"));
1360 gtk_box_append(GTK_BOX(right), frame);
1361
1362 city_dialog_map_create(pdialog, &pdialog->happiness.map_canvas);
1364 }
1365
1366 /* Lower right: happiness */
1368 gtk_box_append(GTK_BOX(right), pdialog->happiness.widget);
1371 pdialog->shell));
1372
1373 /* Show page */
1375}
1376
1377/***********************************************************************/
1380static void create_and_append_cma_page(struct city_dialog *pdialog)
1381{
1382 GtkWidget *page, *label;
1383 const char *tab_title = _("_Governor");
1384
1386
1388
1389 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1390
1391 pdialog->cma_editor = create_cma_dialog(pdialog->pcity, low_citydlg);
1392 gtk_box_append(GTK_BOX(page), pdialog->cma_editor->shell);
1393
1395}
1396
1397/**********************************************************************/
1400/**********************************************************************/
1405{
1407 GtkLabel *label = GTK_LABEL(gtk_label_new(_("Counters")));
1408
1409 pdialog->counters.container = NULL;
1410 pdialog->counters.widget = NULL;
1411
1413
1415
1417
1418 gtk_widget_show(page);
1419}
1420
1421/***********************************************************************/
1425{
1426 int i;
1427 GtkWidget *vgrid, *page, *frame, *label, *button;
1429 GtkWidget *group;
1430 const char *tab_title = _("_Settings");
1431 int grid_row = 0;
1432
1433 static const char *new_citizens_output_label[] = {
1434 N_("Luxury"),
1435 N_("Science"),
1436 N_("Gold")
1437 };
1438
1439 static const char *disband_label
1440 = N_("Allow unit production to disband city");
1441
1442 static const char *misc_whichtab_label[NUM_PAGES] = {
1443 N_("Overview page"),
1444 N_("Production page"),
1445 N_("Happiness page"),
1446 N_("Counters Page"),
1447 N_("Governor page"),
1448 N_("This Settings page"),
1449 N_("Last active page")
1450 };
1451
1452 static bool new_citizens_label_done;
1453 static bool misc_whichtab_label_done;
1454
1455 /* Initialize signal_blocker */
1456 pdialog->misc.block_signal = 0;
1457
1458
1459 page = gtk_grid_new();
1465
1467
1469
1470 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1471
1472 /* new_citizens radio */
1473 frame = gtk_frame_new(_("New citizens produce"));
1474 gtk_grid_attach(GTK_GRID(page), frame, 0, 0, 1, 1);
1476
1477 vgrid = gtk_grid_new();
1481
1484
1485 group = NULL;
1486 for (i = 0; i < ARRAY_SIZE(new_citizens_output_label); i++) {
1489 GTK_CHECK_BUTTON(group));
1490 pdialog->misc.new_citizens_radio[i] = button;
1491 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1492 g_signal_connect(button, "toggled",
1493 G_CALLBACK(cityopt_callback), pdialog);
1494 group = button;
1495 }
1496
1497 /* Next is the next-time-open radio group in the right column */
1498 frame = gtk_frame_new(_("Next time open"));
1499 gtk_grid_attach(GTK_GRID(page), frame, 1, 0, 1, 1);
1501
1502 vgrid = gtk_grid_new();
1503 grid_row = 0;
1507
1510
1511 group = NULL;
1512 for (i = 0; i < ARRAY_SIZE(misc_whichtab_label); i++) {
1515 GTK_CHECK_BUTTON(group));
1516 pdialog->misc.whichtab_radio[i] = button;
1517 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1518 g_signal_connect(button, "toggled",
1520 group = button;
1521 }
1522
1523 /* Now we go back and fill the hbox rename */
1524 frame = gtk_frame_new(_("City"));
1525 gtk_widget_set_margin_top(frame, 12);
1527 gtk_grid_attach(GTK_GRID(page), frame, 0, 1, 1, 1);
1528
1529 vgrid = gtk_grid_new();
1530 grid_row = 0;
1534
1535 button = gtk_button_new_with_mnemonic(_("R_ename..."));
1536 pdialog->misc.rename_command = button;
1537 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1538 g_signal_connect(button, "clicked",
1539 G_CALLBACK(rename_callback), pdialog);
1540
1542
1543 /* The disband-city-on-unit-production button */
1545 pdialog->misc.disband_on_settler = button;
1546 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1547 g_signal_connect(button, "toggled",
1548 G_CALLBACK(cityopt_callback), pdialog);
1549
1550 /* We choose which page to popup by default */
1552 (pdialog->
1554 TRUE);
1555
1556 set_cityopt_values(pdialog);
1557
1559
1560 if (new_dialog_def_page == (NUM_PAGES - 1)) {
1562 last_page);
1563 } else {
1566 }
1567}
1568
1569/***********************************************************************/
1578{
1579 struct city_dialog *pdialog;
1581 GtkWidget *vbox, *hbox, *cbox;
1584 int ccol = 0;
1586 struct player *owner;
1587
1590 }
1591
1592 pdialog = fc_malloc(sizeof(struct city_dialog));
1593 pdialog->pcity = pcity;
1594 pdialog->sell_shell = NULL;
1595 pdialog->rename_shell = NULL;
1596 pdialog->happiness.map_canvas.sw = NULL; /* Make sure NULL if spy */
1597 pdialog->happiness.map_canvas.darea = NULL; /* Ditto */
1598 pdialog->happiness.citizens = NULL; /* Ditto */
1599 pdialog->counters.widget = NULL;
1600 pdialog->counters.container = NULL;
1601 pdialog->production.buy_command = NULL;
1602 pdialog->production.production_label = NULL;
1603 pdialog->production.production_bar = NULL;
1604 pdialog->cma_editor = NULL;
1608
1609 pdialog->shell = gtk_dialog_new();
1611 setup_dialog(pdialog->shell, toplevel);
1612
1613 g_signal_connect(pdialog->shell, "destroy",
1615 gtk_widget_set_name(pdialog->shell, "Freeciv");
1616
1617 gtk_widget_realize(pdialog->shell);
1618
1619 /* Keep the icon of the executable on Windows (see PR#36491) */
1620#ifndef FREECIV_MSWINDOWS
1621 {
1622 gtk_window_set_icon_name(GTK_WINDOW(pdialog->shell), "citydlg");
1623 }
1624#endif /* FREECIV_MSWINDOWS */
1625
1626 /* Restore size of the city dialog. */
1630
1631 pdialog->popover = NULL;
1632
1636 gtk_box_append(GTK_BOX(vbox), hbox);
1637
1638 /**** Citizens bar here ****/
1639 cbox = gtk_grid_new();
1640 gtk_box_append(GTK_BOX(hbox), cbox);
1641
1644
1648 pdialog->citizen_pics = gtk_picture_new();
1649
1658 gtk_grid_attach(GTK_GRID(cbox), pdialog->citizen_pics, ccol++, 0, 1, 1);
1659
1661 g_signal_connect(controller, "pressed",
1662 G_CALLBACK(citizens_callback), pdialog);
1664
1665 /**** City name label here ****/
1666 pdialog->name_label = gtk_label_new(NULL);
1671
1672 /**** -Start of Notebook- ****/
1673
1674 pdialog->notebook = gtk_notebook_new();
1677 gtk_box_append(GTK_BOX(vbox), pdialog->notebook);
1678
1682
1683 owner = city_owner(pcity);
1684
1685 /* Only create these tabs if not a spy */
1689 }
1690
1692
1693 if (owner == client_player()
1694 && !client_is_observer()) {
1697 } else {
1700 }
1701
1702 /**** End of Notebook ****/
1703
1704 /* Bottom buttons */
1705
1706 pdialog->show_units_command =
1707 gtk_dialog_add_button(GTK_DIALOG(pdialog->shell), _("_List present units..."), CDLGR_UNITS);
1708
1709 g_signal_connect(GTK_DIALOG(pdialog->shell), "response",
1711
1712 pdialog->prev_command = gtk_button_new_from_icon_name("go-previous");
1714 GTK_WIDGET(pdialog->prev_command), 1);
1715
1716 pdialog->next_command = gtk_button_new_from_icon_name("go-next");
1718 GTK_WIDGET(pdialog->next_command), 2);
1719
1720 if (owner != client_player()) {
1723 }
1724
1726 _("_Close"), GTK_RESPONSE_CLOSE);
1727
1730
1732 G_CALLBACK(close_callback), pdialog);
1733
1734 g_signal_connect(pdialog->prev_command, "clicked",
1736
1737 g_signal_connect(pdialog->next_command, "clicked",
1739
1740 /* Some other things we gotta do */
1741
1743 g_signal_connect(controller, "key-pressed",
1746
1748
1750
1751 /* Need to do this every time a new dialog is opened. */
1753
1755
1757
1758 return pdialog;
1759}
1760
1761/**************** Functions to update parts of the dialog *****************/
1762
1763/**********************************************************************/
1766static void city_dialog_update_counters(struct city_dialog *pdialog)
1767{
1772 char int_val[101];
1773 char *text;
1774 int text_size;
1775
1776 if (NULL != pdialog->counters.widget) {
1778 GTK_WIDGET(pdialog->counters.widget));
1779 }
1780
1781 if (NULL == pdialog->counters.container) {
1783 }
1784
1788
1792 counterValue = GTK_LABEL(gtk_label_new(_("Current value is: ")));
1794 fc_snprintf(int_val, sizeof(int_val), "%d", pdialog->pcity->counter_values[counter_index(pcount)]);
1798
1800 counterValue = GTK_LABEL(gtk_label_new(_("Activated once value equal or higher than: ")));
1802 fc_snprintf(int_val, sizeof(int_val), "%d", pcount->checkpoint);
1806
1807 text_size = 0;
1808 if (NULL != pcount->helptext) {
1809 strvec_iterate(pcount->helptext, text_) {
1812 }
1813 if (0 < text_size) {
1814 text = malloc(text_size+1);
1815 text_size = 0;
1816 strvec_iterate(pcount->helptext, text_) {
1817 strcpy(&text[text_size], text_);
1821 free(text);
1823 }
1826
1829}
1830
1831/***********************************************************************/
1834static void city_dialog_update_title(struct city_dialog *pdialog)
1835{
1836 gchar *buf;
1837 const gchar *now;
1838
1839 if (city_unhappy(pdialog->pcity)) {
1840 /* TRANS: city dialog title */
1841 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - DISORDER"),
1842 city_name_get(pdialog->pcity),
1844 } else if (city_celebrating(pdialog->pcity)) {
1845 /* TRANS: city dialog title */
1846 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - celebrating"),
1847 city_name_get(pdialog->pcity),
1849 } else if (city_happy(pdialog->pcity)) {
1850 /* TRANS: city dialog title */
1851 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - happy"),
1852 city_name_get(pdialog->pcity),
1854 } else {
1855 /* TRANS: city dialog title */
1856 buf = g_strdup_printf(_("<b>%s</b> - %s citizens"),
1857 city_name_get(pdialog->pcity),
1859 }
1860
1862 if (strcmp(now, buf) != 0) {
1865 }
1866
1867 g_free(buf);
1868}
1869
1870/***********************************************************************/
1873static void city_dialog_update_citizens(struct city_dialog *pdialog)
1874{
1875 enum citizen_category categories[MAX_CITY_SIZE];
1878 struct city *pcity = pdialog->pcity;
1879 int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
1880 cairo_t *cr;
1881
1882 /* If there is not enough space we stack the icons. We draw from left to */
1883 /* right. width is how far we go to the right for each drawn pixmap. The */
1884 /* last icon is always drawn in full, and so has reserved */
1885 /* tileset_small_sprite_width(tileset) pixels. */
1886
1888 if (num_citizens > 1) {
1890 / (num_citizens - 1));
1891 } else {
1892 width = full_width;
1893 }
1894 pdialog->cwidth = width;
1895
1896 /* overview page */
1897 /* keep these values in sync with create_city_dialog */
1900
1901 cr = cairo_create(pdialog->citizen_surface);
1902
1903 for (i = 0; i < num_citizens; i++) {
1905 get_citizen_sprite(tileset, categories[i], i, pcity)->surface,
1906 i * width, 0);
1907 cairo_rectangle(cr, i * width, 0,
1908 /* Always draw last citizen in full */
1909 i + 1 < num_citizens ? width : full_width,
1911 cairo_fill(cr);
1912 }
1913
1914 total_used_width = (i - 1) * width + full_width;
1915
1917 /* Clear the rest of the area.
1918 * Note that this might still be necessary even in cases where
1919 * num_citizens > NUM_CITIZENS_SHOWN, if the available width cannot be
1920 * divided perfectly. */
1925 cairo_fill(cr);
1926 }
1927
1928 cairo_destroy(cr);
1929
1931 pdialog->citizen_surface);
1932
1934}
1935
1936/***********************************************************************/
1940 struct city_dialog *pdialog)
1941{
1942 int i, illness = 0;
1943 char buf[NUM_INFO_FIELDS][512];
1944 struct city *pcity = pdialog->pcity;
1945 int granaryturns;
1946 int non_workers = city_specialists(pcity);
1947
1948 /* fill the buffers with the necessary info */
1949 if (non_workers) {
1950 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
1951 pcity->size, non_workers);
1952 } else {
1953 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d", pcity->size);
1954 }
1955 fc_snprintf(buf[INFO_FOOD], sizeof(buf[INFO_FOOD]), "%3d (%+4d)",
1956 pcity->prod[O_FOOD], pcity->surplus[O_FOOD]);
1957 fc_snprintf(buf[INFO_SHIELD], sizeof(buf[INFO_SHIELD]), "%3d (%+4d)",
1958 pcity->prod[O_SHIELD] + pcity->waste[O_SHIELD],
1959 pcity->surplus[O_SHIELD]);
1960 fc_snprintf(buf[INFO_TRADE], sizeof(buf[INFO_TRADE]), "%3d (%+4d)",
1961 pcity->surplus[O_TRADE] + pcity->waste[O_TRADE],
1962 pcity->surplus[O_TRADE]);
1963 fc_snprintf(buf[INFO_GOLD], sizeof(buf[INFO_GOLD]), "%3d (%+4d)",
1964 pcity->prod[O_GOLD], pcity->surplus[O_GOLD]);
1965 fc_snprintf(buf[INFO_LUXURY], sizeof(buf[INFO_LUXURY]), "%3d",
1966 pcity->prod[O_LUXURY]);
1967 fc_snprintf(buf[INFO_SCIENCE], sizeof(buf[INFO_SCIENCE]), "%3d",
1968 pcity->prod[O_SCIENCE]);
1969 fc_snprintf(buf[INFO_GRANARY], sizeof(buf[INFO_GRANARY]), "%4d/%-4d",
1971
1973 if (granaryturns == 0) {
1974 /* TRANS: city growth is blocked. Keep short. */
1975 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("blocked"));
1976 } else if (granaryturns == FC_INFINITY) {
1977 /* TRANS: city is not growing. Keep short. */
1978 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("never"));
1979 } else {
1980 /* A negative value means we'll have famine in that many turns.
1981 But that's handled down below. */
1982 /* TRANS: city growth turns. Keep short. */
1984 PL_("%d turn", "%d turns", abs(granaryturns)),
1985 abs(granaryturns));
1986 }
1988 pcity->waste[O_TRADE]);
1989 fc_snprintf(buf[INFO_WASTE], sizeof(buf[INFO_WASTE]), "%4d",
1990 pcity->waste[O_SHIELD]);
1991 fc_snprintf(buf[INFO_CULTURE], sizeof(buf[INFO_CULTURE]), "%4d",
1992 pcity->client.culture);
1994 pcity->pollution);
1995 if (!game.info.illness_on) {
1996 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), " -.-");
1997 } else {
1999 /* illness is in tenth of percent */
2000 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), "%5.1f%%",
2001 (float)illness / 10.0);
2002 }
2003 if (pcity->steal) {
2004 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), PL_("%d time", "%d times", pcity->steal),
2005 pcity->steal);
2006 } else {
2007 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), _("Not stolen"));
2008 }
2009
2011
2012 /* stick 'em in the labels */
2013 for (i = 0; i < NUM_INFO_FIELDS; i++) {
2015 }
2016
2017 /*
2018 * Make use of the emergency-indicating styles set up for certain labels
2019 * in create_city_info_table().
2020 */
2021 /* For starvation, the "4" below is arbitrary. 3 turns should be enough
2022 * of a warning. */
2023 if (granaryturns > -4 && granaryturns < 0) {
2025 } else {
2027 }
2028
2029 if (granaryturns == 0 || pcity->surplus[O_FOOD] < 0) {
2031 } else {
2033 }
2034
2035 /* Someone could add the color &orange for better granularity here */
2036 if (pcity->pollution >= 10) {
2038 } else {
2040 }
2041
2042 /* Illness is in tenth of percent, i.e 100 == 10.0% */
2043 if (illness >= 100) {
2045 } else {
2047 }
2048}
2049
2050/***********************************************************************/
2053static void city_dialog_update_map(struct city_dialog *pdialog)
2054{
2055 struct canvas store = FC_STATIC_CANVAS_INIT;
2056
2057 store.surface = pdialog->map_canvas_store_unscaled;
2058
2059 /* The drawing is done in three steps.
2060 * 1. First we render to a pixmap with the appropriate canvas size.
2061 * 2. Then the pixmap is rendered into a pixbuf of equal size.
2062 * 3. Finally this pixbuf is composited and scaled onto the GtkImage's
2063 * target pixbuf.
2064 */
2065
2066 city_dialog_redraw_map(pdialog->pcity, &store);
2067
2068 /* draw to real window */
2069 draw_map_canvas(pdialog);
2070}
2071
2072/***********************************************************************/
2075static void city_dialog_update_building(struct city_dialog *pdialog)
2076{
2077 char buf[32], buf2[200];
2078 gdouble pct;
2079 GtkListStore *store;
2081 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2082 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2083 int targets_used, item;
2084 struct city *pcity = pdialog->pcity;
2086 const char *descr = city_production_name_translation(pcity);
2088
2089 if (pdialog->overview.buy_command != NULL) {
2091 }
2092 if (pdialog->production.buy_command != NULL) {
2094 }
2095
2096 /* Make sure build slots info is up to date */
2097 if (pdialog->production.production_label != NULL) {
2098 int build_slots = city_build_slots(pcity);
2099
2100 /* Only display extra info if more than one slot is available */
2101 if (build_slots > 1) {
2102 fc_snprintf(buf2, sizeof(buf2),
2103 /* TRANS: never actually used with built_slots <= 1 */
2104 PL_("Production (up to %d unit per turn):",
2105 "Production (up to %d units per turn):", build_slots),
2106 build_slots);
2109 } else {
2111 GTK_LABEL(pdialog->production.production_label), _("Production:"));
2112 }
2113 }
2114
2115 /* Update what the city is working on */
2116 get_city_dialog_production(pcity, buf, sizeof(buf));
2117
2118 if (cost > 0) {
2119 pct = (gdouble) pcity->shield_stock / (gdouble) cost;
2120 pct = CLAMP(pct, 0.0, 1.0);
2121 } else {
2122 pct = 1.0;
2123 }
2124
2125 if (pdialog->overview.production_bar != NULL) {
2126 fc_snprintf(buf2, sizeof(buf2), "%s%s\n%s", descr,
2127 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2132 }
2133
2134 if (pdialog->production.production_bar != NULL) {
2135 fc_snprintf(buf2, sizeof(buf2), "%s%s: %s", descr,
2136 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2141 }
2142
2143 store = pdialog->overview.change_production_store;
2144 if (store != NULL) {
2145 int cur = -1;
2146 int actcount = 0;
2147
2148 if (pdialog->overview.production_combo != NULL) {
2150 -1);
2151 }
2152
2153 gtk_list_store_clear(store);
2154
2156 = collect_eventually_buildable_targets(targets, pdialog->pcity, FALSE);
2157 name_and_sort_items(targets, targets_used, items, FALSE, pcity);
2158
2159 for (item = 0; item < targets_used; item++) {
2160 if (can_city_build_now(&(wld.map), pcity, &items[item].item)) {
2161 const char *name;
2162 struct sprite *sprite;
2163 GdkPixbuf *pix;
2164 struct universal *target = &items[item].item;
2165 bool useless;
2166
2167 if (VUT_UTYPE == target->kind) {
2171 useless = FALSE;
2172 } else {
2176 }
2178 gtk_list_store_append(store, &iter);
2179 gtk_list_store_set(store, &iter, 0, pix,
2180 1, name, 3, useless,
2181 2, (gint)cid_encode(items[item].item), -1);
2182 if (pix != NULL) {
2184 }
2185
2186 if (are_universals_equal(target, &pcity->production)) {
2187 cur = actcount;
2188 }
2189
2190 actcount++;
2191 }
2192 }
2193
2194 if (pdialog->overview.production_combo != NULL) {
2196 cur);
2197 }
2198 }
2199}
2200
2201/***********************************************************************/
2205{
2206 int item, targets_used;
2207 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2208 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2209 GtkTreeModel *model;
2210 GtkListStore *store;
2211
2212 const char *tooltip_sellable = _("Press <b>ENTER</b> or double-click to "
2213 "sell an improvement.");
2214 const char *tooltip_great_wonder = _("Great Wonder - cannot be sold.");
2215 const char *tooltip_small_wonder = _("Small Wonder - cannot be sold.");
2216
2217 model =
2219 store = GTK_LIST_STORE(model);
2220
2222 name_and_sort_items(targets, targets_used, items, FALSE, pdialog->pcity);
2223
2224 gtk_list_store_clear(store);
2225
2226 for (item = 0; item < targets_used; item++) {
2227 GdkPixbuf *pix;
2228 GtkTreeIter it;
2229 int upkeep;
2230 struct sprite *sprite;
2231 struct universal target = items[item].item;
2232
2233 fc_assert_action(VUT_IMPROVEMENT == target.kind, continue);
2234 /* This takes effects (like Adam Smith's) into account. */
2235 upkeep = city_improvement_upkeep(pdialog->pcity, target.value.building);
2237
2239 gtk_list_store_append(store, &it);
2240 gtk_list_store_set(store, &it,
2241 0, target.value.building,
2242 1, pix,
2243 2, items[item].descr,
2244 3, upkeep,
2245 4,
2247 target.value.building),
2248 5,
2251 (is_small_wonder(target.value.building) ?
2253 -1);
2255 }
2256}
2257
2258/***********************************************************************/
2262{
2263 struct unit_list *units;
2264 struct unit_node_vector *nodes;
2265 int n, m, i;
2266 gchar *buf;
2268 const struct civ_map *nmap = &(wld.map);
2269
2270 if (NULL != client.conn.playing
2271 && city_owner(pdialog->pcity) != client.conn.playing) {
2272 units = pdialog->pcity->client.info_units_supported;
2273 } else {
2274 units = pdialog->pcity->units_supported;
2275 }
2276
2277 nodes = &pdialog->overview.supported_units;
2278
2279 n = unit_list_size(units);
2280 m = unit_node_vector_size(nodes);
2281
2282 if (m > n) {
2283 i = 0;
2285 if (i++ >= n) {
2287 elt->cmd);
2288 }
2290
2292 } else {
2293 for (i = m; i < n; i++) {
2294 GtkWidget *cmd, *pix;
2295 struct unit_node node;
2296
2297 cmd = gtk_button_new();
2298 node.cmd = cmd;
2299
2301
2302 pix = gtk_picture_new();
2303 node.pix = pix;
2305
2307
2309 cmd);
2310
2311 node.left = NULL;
2312 node.middle = NULL;
2313 node.right = NULL;
2314
2315 unit_node_vector_append(nodes, node);
2316 }
2317 }
2318
2319 i = 0;
2320 unit_list_iterate(units, punit) {
2321 struct unit_node *pnode;
2322 int happy_cost = city_unit_unhappiness(nmap, punit, &free_unhappy);
2323
2324 pnode = unit_node_vector_get(nodes, i);
2325 if (pnode) {
2326 GtkWidget *cmd, *pix;
2329
2330 cmd = pnode->cmd;
2331 pix = pnode->pix;
2332
2334 punit->upkeep, happy_cost);
2335
2336 if (pnode->left != NULL) {
2340 }
2341
2343
2345 g_signal_connect(controller, "pressed",
2349 pnode->left = controller;
2353 g_signal_connect(controller, "released",
2357 pnode->middle = controller;
2361 g_signal_connect(controller, "released",
2365 pnode->right = controller;
2366
2367 if (city_owner(pdialog->pcity) != client.conn.playing) {
2369 } else {
2371 }
2372
2375 }
2376 i++;
2378
2379 buf = g_strdup_printf(_("Supported units %d"), n);
2381 g_free(buf);
2382}
2383
2384/***********************************************************************/
2388{
2389 struct unit_list *units;
2390 struct unit_node_vector *nodes;
2391 int n, m, i;
2392 gchar *buf;
2393
2394 if (NULL != client.conn.playing
2395 && city_owner(pdialog->pcity) != client.conn.playing) {
2396 units = pdialog->pcity->client.info_units_present;
2397 } else {
2398 units = pdialog->pcity->tile->units;
2399 }
2400
2401 nodes = &pdialog->overview.present_units;
2402
2403 n = unit_list_size(units);
2404 m = unit_node_vector_size(nodes);
2405
2406 if (m > n) {
2407 i = 0;
2409 if (i++ >= n) {
2411 elt->cmd);
2412 }
2414
2416 } else {
2417 for (i = m; i < n; i++) {
2418 GtkWidget *cmd, *pix;
2419 struct unit_node node;
2420
2421 cmd = gtk_button_new();
2422 node.cmd = cmd;
2423
2425
2426 pix = gtk_picture_new();
2427 node.pix = pix;
2429
2431
2433 cmd);
2434
2435 node.left = NULL;
2436 node.middle = NULL;
2437 node.right = NULL;
2438
2439 unit_node_vector_append(nodes, node);
2440 }
2441 }
2442
2443 i = 0;
2444 unit_list_iterate(units, punit) {
2445 struct unit_node *pnode;
2446
2447 pnode = unit_node_vector_get(nodes, i);
2448 if (pnode) {
2449 GtkWidget *cmd, *pix;
2452
2453 cmd = pnode->cmd;
2454 pix = pnode->pix;
2455
2457
2458 if (pnode->left != NULL) {
2462 }
2463
2465
2467 g_signal_connect(controller, "pressed",
2471 pnode->left = controller;
2475 g_signal_connect(controller, "released",
2479 pnode->middle = controller;
2483 g_signal_connect(controller, "released",
2487 pnode->right = controller;
2488
2489 if (city_owner(pdialog->pcity) != client.conn.playing) {
2491 } else {
2493 }
2494
2497 }
2498 i++;
2500
2501 buf = g_strdup_printf(_("Present units %d"), n);
2503 g_free(buf);
2504}
2505
2506/***********************************************************************/
2514{
2515 int count = 0;
2516 int city_number;
2517
2518 if (NULL != client.conn.playing) {
2520 } else {
2521 city_number = FC_INFINITY; /* ? */
2522 }
2523
2524 /* The first time, we see if all the city dialogs are open */
2526 if (city_owner(pdialog->pcity) == client.conn.playing) {
2527 count++;
2528 }
2530
2531 if (count == city_number) { /* All are open, shouldn't prev/next */
2533 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), FALSE);
2534 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), FALSE);
2536 } else {
2538 if (city_owner(pdialog->pcity) == client.conn.playing) {
2539 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), TRUE);
2540 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), TRUE);
2541 }
2543 }
2544}
2545
2546/***********************************************************************/
2549static void citydlg_response_callback(GtkDialog *dlg, gint response,
2550 void *data)
2551{
2552 switch (response) {
2553 case CDLGR_UNITS:
2554 show_units_response(data);
2555 break;
2556 }
2557}
2558
2559/***********************************************************************/
2562static void show_units_response(void *data)
2563{
2564 struct city_dialog *pdialog = (struct city_dialog *) data;
2565 struct tile *ptile = pdialog->pcity->tile;
2566
2567 if (unit_list_size(ptile->units)) {
2569 }
2570}
2571
2572/***********************************************************************/
2582static bool create_unit_menu(struct city_dialog *pdialog, struct unit *punit,
2583 GtkWidget *wdg, bool supported)
2584{
2585 GMenu *menu;
2586 GActionGroup *group;
2587 GSimpleAction *act;
2588
2589 if (!can_client_issue_orders()) {
2590 return FALSE;
2591 }
2592
2593 if (pdialog->popover != NULL) {
2595 }
2596
2598 menu = g_menu_new();
2599
2600 if (supported) {
2601 act = g_simple_action_new("center", NULL);
2602 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2606 menu_item_append_unref(menu, g_menu_item_new(_("Cen_ter"), "win.center"));
2607 }
2608
2609 act = g_simple_action_new("activate", NULL);
2610 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2614 menu_item_append_unref(menu, g_menu_item_new(_("_Activate unit"),
2615 "win.activate"));
2616
2617 act = g_simple_action_new("activate_close", NULL);
2618 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2620
2621 if (supported) {
2622 g_signal_connect(act, "activate",
2625 } else {
2626 g_signal_connect(act, "activate",
2629 }
2630
2632 g_menu_item_new(_("Activate unit, _close dialog"),
2633 "win.activate_close"));
2634
2635 if (!supported) {
2636 act = g_simple_action_new("load", NULL);
2637 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2642 menu_item_append_unref(menu, g_menu_item_new(_("_Load unit"), "win.load"));
2643
2644 act = g_simple_action_new("unload", NULL);
2645 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2653 unit_tile(punit)));
2654 menu_item_append_unref(menu, g_menu_item_new(_("_Unload unit"),
2655 "win.unload"));
2656
2657 act = g_simple_action_new("sentry", NULL);
2658 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2666 menu_item_append_unref(menu, g_menu_item_new(_("_Sentry unit"),
2667 "win.sentry"));
2668
2669 act = g_simple_action_new("fortify", NULL);
2670 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2678 menu_item_append_unref(menu, g_menu_item_new(_("_Fortify unit"),
2679 "win.fortify"));
2680 }
2681
2682 act = g_simple_action_new("disband", NULL);
2683 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2689 menu_item_append_unref(menu, g_menu_item_new(_("_Disband unit"),
2690 "win.disband"));
2691
2692 if (!supported) {
2693 act = g_simple_action_new("rehome", NULL);
2694 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2700 pdialog->pcity));
2703 "win.rehome"));
2704
2705 act = g_simple_action_new("upgrade", NULL);
2706 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2715 != NULL);
2716 menu_item_append_unref(menu, g_menu_item_new(_("U_pgrade unit"),
2717 "win.upgrade"));
2718 }
2719
2721 g_object_ref(pdialog->popover);
2722 gtk_widget_insert_action_group(pdialog->popover, "win", group);
2724
2725
2727
2728 return TRUE;
2729}
2730
2731/***********************************************************************/
2735 double x, double y, gpointer data)
2736{
2737 struct city_dialog *pdialog;
2738 struct city *pcity;
2739 struct unit *punit =
2740 player_unit_by_number(client_player(), (size_t) data);
2741
2742 if (NULL != punit
2743 && NULL != (pcity = game_city_by_number(punit->homecity))
2744 && NULL != (pdialog = get_city_dialog(pcity))) {
2745
2746 return create_unit_menu(pdialog, punit,
2748 TRUE);
2749 }
2750
2751 return TRUE;
2752}
2753
2754/***********************************************************************/
2758 double x, double y, gpointer data)
2759{
2760 struct city_dialog *pdialog;
2761 struct city *pcity;
2762 struct unit *punit =
2763 player_unit_by_number(client_player(), (size_t) data);
2764
2765 if (NULL != punit
2766 && NULL != (pcity = tile_city(unit_tile(punit)))
2767 && NULL != (pdialog = get_city_dialog(pcity))) {
2768
2769 return create_unit_menu(pdialog, punit,
2771 FALSE);
2772 }
2773
2774 return TRUE;
2775}
2776
2777/***********************************************************************/
2782 int n_press, double x, double y,
2783 gpointer data)
2784{
2785 struct city_dialog *pdialog;
2786 struct city *pcity;
2787 struct unit *punit =
2788 player_unit_by_number(client_player(), (size_t) data);
2789
2790 if (NULL != punit
2791 && NULL != (pcity = tile_city(unit_tile(punit)))
2792 && NULL != (pdialog = get_city_dialog(pcity))
2795 close_city_dialog(pdialog);
2796 }
2797
2798 return TRUE;
2799}
2800
2801/***********************************************************************/
2806 double x, double y, gpointer data)
2807{
2808 struct city_dialog *pdialog;
2809 struct city *pcity;
2810 struct unit *punit =
2811 player_unit_by_number(client_player(), (size_t) data);
2812
2813 if (NULL != punit
2814 && NULL != (pcity = game_city_by_number(punit->homecity))
2815 && NULL != (pdialog = get_city_dialog(pcity))
2818 close_city_dialog(pdialog);
2819 }
2820
2821 return TRUE;
2822}
2823
2824/***********************************************************************/
2828 double x, double y, gpointer data)
2829{
2830 struct unit *punit =
2831 player_unit_by_number(client_player(), (size_t) data);
2832
2833 if (NULL != punit
2836 }
2837
2838 return TRUE;
2839}
2840
2841/***********************************************************************/
2846static void close_citydlg_unit_popover(struct city_dialog *pdialog)
2847{
2848 if (pdialog->popover != NULL) {
2849 gtk_widget_unparent(pdialog->popover);
2850 g_object_unref(pdialog->popover);
2851 pdialog->popover = NULL;
2852 }
2853}
2854
2855/***********************************************************************/
2859 gpointer data)
2860{
2861 struct unit *punit =
2863
2864 if (NULL != punit) {
2866 }
2867
2869}
2870
2871/***********************************************************************/
2875 gpointer data)
2876{
2877 struct unit *punit =
2879
2880 if (NULL != punit) {
2881 /* FIXME: If unit is not idle to begin with, we can only request
2882 * idling, and as we have no server reply yet,
2883 * the unit_focus_try() below will fail. */
2886 }
2887
2889}
2890
2891/***********************************************************************/
2896 GVariant *parameter,
2897 gpointer data)
2898{
2899 struct unit *punit =
2901
2902 if (NULL != punit) {
2903 struct city *pcity =
2905
2906 /* FIXME: If unit is not idle to begin with, we can only request
2907 * idling, and as we have no server reply yet,
2908 * the unit_focus_try() below will fail. */
2911
2912 if (NULL != pcity) {
2913 struct city_dialog *pdialog = get_city_dialog(pcity);
2914
2915 if (NULL != pdialog) {
2916 close_city_dialog(pdialog);
2917 }
2918 }
2919 }
2920
2922}
2923
2924/***********************************************************************/
2929 GVariant *parameter,
2930 gpointer data)
2931{
2932 struct unit *punit =
2934
2935 if (NULL != punit) {
2936 struct city *pcity = tile_city(unit_tile(punit));
2937
2938 /* FIXME: If unit is not idle to begin with, we can only request
2939 * idling, and as we have no server reply yet,
2940 * the unit_focus_try() below will fail. */
2943
2944 if (NULL != pcity) {
2945 struct city_dialog *pdialog = get_city_dialog(pcity);
2946
2947 if (NULL != pdialog) {
2948 close_city_dialog(pdialog);
2949 }
2950 }
2951 }
2952
2954}
2955
2956/***********************************************************************/
2960 gpointer data)
2961{
2962 struct unit *punit =
2964
2965 if (NULL != punit) {
2967 }
2968
2970}
2971
2972/***********************************************************************/
2976 gpointer data)
2977{
2978 struct unit *punit =
2980
2981 if (NULL != punit) {
2983 }
2984
2986}
2987
2988/***********************************************************************/
2992 gpointer data)
2993{
2994 struct unit *punit =
2996
2997 if (NULL != punit) {
2999 }
3000
3002}
3003
3004/***********************************************************************/
3008 gpointer data)
3009{
3010 struct unit *punit =
3012
3013 if (NULL != punit) {
3015 }
3016
3018}
3019
3020/***********************************************************************/
3024 gpointer data)
3025{
3026 struct unit_list *punits;
3027 struct unit *punit =
3029
3030 if (NULL == punit) {
3031 return;
3032 }
3033
3038
3040}
3041
3042/***********************************************************************/
3047 gpointer data)
3048{
3049 struct unit *punit =
3051
3052 if (NULL != punit) {
3054 }
3055
3057}
3058
3059/***********************************************************************/
3063 gpointer data)
3064{
3065 struct unit_list *punits;
3066 struct unit *punit =
3068
3069 if (NULL == punit) {
3070 return;
3071 }
3072
3077
3079}
3080
3081/******** Callbacks for citizen bar, map funcs that are not update ********/
3082
3083/***********************************************************************/
3088 double x, double y, gpointer data)
3089{
3090 struct city_dialog *pdialog = data;
3091 struct city *pcity = pdialog->pcity;
3092 int citnum, tlen, len;
3093
3094 if (!can_client_issue_orders()) {
3095 return FALSE;
3096 }
3097
3099 len = (city_size_get(pcity) - 1) * pdialog->cwidth + tlen;
3100
3101 if (x > len) {
3102 /* no citizen that far to the right */
3103 return FALSE;
3104 }
3105 citnum = MIN(city_size_get(pcity) - 1, x / pdialog->cwidth);
3106
3108
3109 return TRUE;
3110}
3111
3112/***********************************************************************/
3116{
3117 enum unit_activity act = (enum unit_activity)GPOINTER_TO_INT(data);
3118 struct city *pcity = workertask_req.owner;
3119 struct tile *ptile = workertask_req.loc;
3120 struct packet_worker_task task;
3121
3122 task.city_id = pcity->id;
3123
3124 if (act == ACTIVITY_LAST) {
3125 task.tgt = -1;
3126 task.want = 0;
3127 } else {
3128 enum extra_cause cause = activity_to_extra_cause(act);
3130 struct extra_type *tgt;
3131
3132 if (cause != EC_NONE) {
3133 tgt = next_extra_for_tile(ptile, cause, city_owner(pcity), NULL);
3134 } else if (rmcause != ERM_NONE) {
3135 tgt = prev_extra_in_tile(ptile, rmcause, city_owner(pcity), NULL);
3136 } else {
3137 tgt = NULL;
3138 }
3139
3140 if (tgt == NULL) {
3141 struct terrain *pterr = tile_terrain(ptile);
3142
3143 if ((act != ACTIVITY_TRANSFORM
3144 || pterr->transform_result == NULL || pterr->transform_result == pterr)
3145 && (act != ACTIVITY_CULTIVATE || pterr->cultivate_result == NULL)
3146 && (act != ACTIVITY_PLANT || pterr->plant_result == NULL)) {
3147 /* No extra to order */
3148 output_window_append(ftc_client, _("There's no suitable extra to order."));
3149
3150 return;
3151 }
3152
3153 task.tgt = -1;
3154 } else {
3155 task.tgt = extra_index(tgt);
3156 }
3157
3158 task.want = 100;
3159 }
3160
3161 task.tile_id = ptile->index;
3162 task.activity = act;
3163
3165}
3166
3167/***********************************************************************/
3174
3175/***********************************************************************/
3178static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
3179{
3181 GtkWidget *shl;
3182 struct terrain *pterr = tile_terrain(ptile);
3183 struct universal for_terr = { .kind = VUT_TERRAIN,
3184 .value = { .terrain = pterr }};
3185 struct worker_task *ptask;
3186
3188 workertask_req.owner = pcity;
3189 workertask_req.loc = ptile;
3190
3192 _("What Action to Request"),
3193 _("Select autosettler activity:"));
3194
3196 if (ptask != NULL) {
3197 choice_dialog_add(shl, _("Clear request"),
3200 }
3201
3203 choice_dialog_add(shl, Q_("?act:Mine"),
3206 }
3207 if (pterr->plant_result != NULL
3209 NULL, &for_terr)) {
3210 choice_dialog_add(shl, _("Plant"),
3213 }
3215 choice_dialog_add(shl, _("Irrigate"),
3218 }
3219 if (pterr->cultivate_result != NULL
3221 NULL, &for_terr)) {
3222 choice_dialog_add(shl, _("Cultivate"),
3225 }
3227 choice_dialog_add(shl, _("Road"),
3230 }
3231 if (pterr->transform_result != pterr && pterr->transform_result != NULL
3233 NULL, &for_terr)) {
3234 choice_dialog_add(shl, _("Transform"),
3237 }
3239 city_owner(pcity), NULL) != NULL) {
3240 choice_dialog_add(shl, _("Clean"),
3243 }
3244
3245 choice_dialog_add(shl, _("_Cancel"), 0, 0, FALSE, NULL);
3247
3249 NULL);
3250 }
3251}
3252
3253/***********************************************************************/
3257 double x, double y, gpointer data)
3258{
3259 struct city_dialog *pdialog = data;
3261
3262 if (!can_client_issue_orders()) {
3263 return FALSE;
3264 }
3265
3266 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
3267 return FALSE;
3268 }
3269
3272
3274 city_map_radius_sq_get(pdialog->pcity),
3275 canvas_x, canvas_y)) {
3277 }
3278
3279 return TRUE;
3280}
3281
3282/***********************************************************************/
3286 double x, double y, gpointer data)
3287{
3288 struct city_dialog *pdialog = data;
3290
3291 if (!can_client_issue_orders()) {
3292 return FALSE;
3293 }
3294
3297
3299 city_map_radius_sq_get(pdialog->pcity),
3300 canvas_x, canvas_y)) {
3301 struct city *pcity = pdialog->pcity;
3302
3303 popup_workertask_dlg(pdialog->pcity,
3304 city_map_to_tile(&(wld.map), pcity->tile,
3306 city_x, city_y));
3307 }
3308
3309 return TRUE;
3310}
3311
3312/***********************************************************************/
3315static void draw_map_canvas(struct city_dialog *pdialog)
3316{
3318 if (pdialog->happiness.map_canvas.darea) { /* in case of spy */
3320 }
3321}
3322
3323/************** Callbacks for Buy, Change, Sell, Worklist *****************/
3324
3325/***********************************************************************/
3328static void buy_callback_response(GtkWidget *w, gint response, gpointer data)
3329{
3330 struct city_dialog *pdialog = data;
3331
3332 if (response == GTK_RESPONSE_YES) {
3333 city_buy_production(pdialog->pcity);
3334 }
3335
3337}
3338
3339/***********************************************************************/
3342static void buy_callback(GtkWidget *w, gpointer data)
3343{
3345 struct city_dialog *pdialog = data;
3346 const char *name = city_production_name_translation(pdialog->pcity);
3347 int value = pdialog->pcity->client.buy_cost;
3348 char buf[1024];
3349
3350 if (!can_client_issue_orders()) {
3351 return;
3352 }
3353
3354 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
3355 "Treasury contains %d gold.",
3356 client_player()->economic.gold),
3357 client_player()->economic.gold);
3358
3359 if (value <= client_player()->economic.gold) {
3363 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3364 PL_("Buy %s for %d gold?\n%s",
3365 "Buy %s for %d gold?\n%s", value),
3366 name, value, buf);
3367 setup_dialog(shell, pdialog->shell);
3368 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3371 pdialog);
3373 } else {
3377 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3378 PL_("%s costs %d gold.\n%s",
3379 "%s costs %d gold.\n%s", value),
3380 name, value, buf);
3381 setup_dialog(shell, pdialog->shell);
3382 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3384 NULL);
3386 }
3387}
3388
3389/***********************************************************************/
3393 struct city_dialog *pdialog)
3394{
3396
3398 && gtk_combo_box_get_active_iter(combo, &iter)) {
3399 cid id;
3400 struct universal univ;
3401
3402 gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter, 2, &id, -1);
3403 univ = cid_production(id);
3404 city_change_production(pdialog->pcity, &univ);
3405 }
3406}
3407
3408/***********************************************************************/
3411static void sell_callback(struct impr_type *pimprove, gpointer data)
3412{
3413 GtkWidget *shl;
3414 struct city_dialog *pdialog = (struct city_dialog *) data;
3415 pdialog->sell_id = improvement_number(pimprove);
3416 int price;
3417
3418 if (!can_client_issue_orders()) {
3419 return;
3420 }
3421
3423 pimprove) != TR_SUCCESS) {
3424 return;
3425 }
3426
3427 price = impr_sell_gold(pimprove);
3432 PL_("Sell %s for %d gold?",
3433 "Sell %s for %d gold?", price),
3434 city_improvement_name_translation(pdialog->pcity, pimprove), price);
3435 setup_dialog(shl, pdialog->shell);
3436 pdialog->sell_shell = shl;
3437
3438 gtk_window_set_title(GTK_WINDOW(shl), _("Sell It!"));
3439
3440 g_signal_connect(shl, "response",
3442
3444}
3445
3446/***********************************************************************/
3449static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
3450{
3451 struct city_dialog *pdialog = data;
3452
3453 if (response == GTK_RESPONSE_YES) {
3454 city_sell_improvement(pdialog->pcity, pdialog->sell_id);
3455 }
3457
3458 pdialog->sell_shell = NULL;
3459}
3460
3461/***********************************************************************/
3466{
3467 GtkTreeModel *model;
3468 GtkTreeIter it;
3469 GdkSeat *seat;
3471 struct impr_type *pimprove;
3472
3474
3475 if (!gtk_tree_model_get_iter(model, &it, path)) {
3476 return;
3477 }
3478
3479 gtk_tree_model_get(model, &it, 0, &pimprove, -1);
3480
3483
3484 if (!(mask & GDK_CONTROL_MASK)) {
3485 sell_callback(pimprove, data);
3486 } else {
3487 if (is_great_wonder(pimprove)) {
3489 } else {
3491 }
3492 }
3493}
3494
3495/************ Callbacks for stuff on the Misc. Settings page **************/
3496
3497/***********************************************************************/
3501{
3502 struct city_dialog *pdialog;
3503
3504 pdialog = (struct city_dialog *) data;
3505
3506 pdialog->rename_shell = input_dialog_create(GTK_WINDOW(pdialog->shell),
3507 /* "shellrenamecity" */
3508 _("Rename City"),
3509 _("What should we rename the city to?"),
3510 city_name_get(pdialog->pcity),
3511 rename_popup_callback, pdialog);
3512}
3513
3514/***********************************************************************/
3517static void rename_popup_callback(gpointer data, gint response,
3518 const char *input)
3519{
3520 struct city_dialog *pdialog = data;
3521
3522 if (pdialog) {
3523 if (response == GTK_RESPONSE_OK) {
3524 city_rename(pdialog->pcity, input);
3525 } /* else CANCEL or DELETE_EVENT */
3526
3527 pdialog->rename_shell = NULL;
3528 }
3529}
3530
3531/***********************************************************************/
3535{
3537}
3538
3539/***********************************************************************/
3543{
3544 struct city_dialog *pdialog = (struct city_dialog *) data;
3545
3546 if (!can_client_issue_orders()) {
3547 return;
3548 }
3549
3550 if (!pdialog->misc.block_signal) {
3551 struct city *pcity = pdialog->pcity;
3553
3554 fc_assert(CITYO_LAST == 3);
3555
3559 }
3562 }
3565 }
3566
3568 pcity->wlcb);
3569 }
3570}
3571
3572/***********************************************************************/
3576static void set_cityopt_values(struct city_dialog *pdialog)
3577{
3578 struct city *pcity = pdialog->pcity;
3579
3580 pdialog->misc.block_signal = 1;
3581
3584
3587 (pdialog->misc.new_citizens_radio[1]), TRUE);
3588 } else if (is_city_option_set(pcity, CITYO_GOLD_SPECIALISTS)) {
3590 (pdialog->misc.new_citizens_radio[2]), TRUE);
3591 } else {
3593 (pdialog->misc.new_citizens_radio[0]), TRUE);
3594 }
3595 pdialog->misc.block_signal = 0;
3596}
3597
3598/******************** Callbacks for: Close, Prev, Next. *******************/
3599
3600/***********************************************************************/
3603static void close_callback(GtkWidget *w, gpointer data)
3604{
3605 close_city_dialog((struct city_dialog *) data);
3606}
3607
3608/***********************************************************************/
3612{
3613 struct city_dialog *pdialog;
3614 int width, height;
3615
3616 /* Save size of the city dialog. */
3618
3619 pdialog = (struct city_dialog *) data;
3620
3622
3624 citizens_dialog_close(pdialog->pcity);
3625 }
3626 close_happiness_dialog(pdialog->pcity);
3627 close_cma_dialog(pdialog->pcity);
3628
3629 /* Save size of the city dialog. */
3632 width,
3636 height,
3638
3639 last_page
3641
3644
3647
3648 if (pdialog->sell_shell) {
3650 }
3651 if (pdialog->rename_shell) {
3653 }
3654
3657
3658 free(pdialog);
3659
3660 /* Need to do this every time a new dialog is closed. */
3662}
3663
3664/***********************************************************************/
3667static void close_city_dialog(struct city_dialog *pdialog)
3668{
3670}
3671
3672/***********************************************************************/
3677{
3678 struct city_dialog *pdialog = (struct city_dialog *) data;
3679 int i, j, dir, size;
3680 struct city *new_pcity = NULL;
3681
3683 return;
3684 }
3685
3687
3689 fc_assert_ret(size >= 1);
3691
3692 if (size == 1) {
3693 return;
3694 }
3695
3696 /* dir = 1 will advance to the city, dir = -1 will get previous */
3697 if (w == GTK_WIDGET(pdialog->next_command)) {
3698 dir = 1;
3699 } else if (w == GTK_WIDGET(pdialog->prev_command)) {
3700 dir = -1;
3701 } else {
3702 /* Always fails. */
3704 || w == GTK_WIDGET(pdialog->prev_command));
3705 dir = 1;
3706 }
3707
3708 for (i = 0; i < size; i++) {
3709 if (pdialog->pcity == city_list_get(client.conn.playing->cities, i)) {
3710 break;
3711 }
3712 }
3713
3714 fc_assert_ret(i < size);
3715
3716 for (j = 1; j < size; j++) {
3718 (i + dir * j + size) % size);
3720
3721 fc_assert_ret(other_pdialog != pdialog);
3722 if (!other_pdialog) {
3724 break;
3725 }
3726 }
3727
3728 if (!new_pcity) {
3729 /* Every other city has an open city dialog. */
3730 return;
3731 }
3732
3733 /* cleanup happiness dialog */
3735 citizens_dialog_close(pdialog->pcity);
3736 }
3737 close_happiness_dialog(pdialog->pcity);
3738
3739 pdialog->pcity = new_pcity;
3740
3741 /* reinitialize happiness, and cma dialogs */
3744 citizens_dialog_display(pdialog->pcity));
3745 }
3747 get_top_happiness_display(pdialog->pcity, low_citydlg, pdialog->shell));
3748 if (!client_is_observer()) {
3749 fc_assert(pdialog->cma_editor != NULL);
3750 pdialog->cma_editor->pcity = new_pcity;
3751 }
3752
3753 reset_city_worklist(pdialog->production.worklist, pdialog->pcity);
3754
3755 can_slide = FALSE;
3756 center_tile_mapcanvas(pdialog->pcity->tile);
3757 can_slide = TRUE;
3758 if (!client_is_observer()) {
3759 set_cityopt_values(pdialog); /* Need not be in real_city_dialog_refresh */
3760 }
3761
3763
3764 /* Recenter the city map(s) */
3766 if (pdialog->happiness.map_canvas.sw) {
3768 }
3769}
3770
3771/***********************************************************************/
3775{
3777 refresh_worklist(pdialog->production.worklist);
3779}
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2011
bool action_ever_possible(action_id action)
Definition actions.c:8092
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:945
#define n
Definition astring.c:77
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
void output_window_append(const struct ft_color color, const char *featured_text)
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:663
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:737
int city_granary_size(int city_size)
Definition city.c:2146
int city_build_slots(const struct city *pcity)
Definition city.c:2946
struct tile * city_map_to_tile(const struct civ_map *nmap, const struct tile *city_center, int city_radius_sq, int city_map_x, int city_map_y)
Definition city.c:305
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1255
bool is_city_option_set(const struct city *pcity, enum city_options option)
Definition city.c:3402
int city_population(const struct city *pcity)
Definition city.c:1191
int city_unit_unhappiness(const struct civ_map *nmap, struct unit *punit, int *free_unhappy)
Definition city.c:3063
bool city_unhappy(const struct city *pcity)
Definition city.c:1626
bool city_celebrating(const struct city *pcity)
Definition city.c:1645
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2884
bool city_happy(const struct city *pcity)
Definition city.c:1614
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
citizens city_specialists(const struct city *pcity)
Definition city.c:3331
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:1013
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1996
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:700
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
citizen_category
Definition city.h:267
#define city_owner(_pcity_)
Definition city.h:563
#define MAX_CITY_SIZE
Definition city.h:106
@ FEELING_FINAL
Definition city.h:284
void get_city_dialog_output_text(const struct city *pcity, Output_type_id otype, char *buf, size_t bufsz)
void get_city_dialog_production(struct city *pcity, char *buffer, size_t buffer_len)
int city_rename(struct city *pcity, const char *name)
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx, enum citizen_category *categories)
int city_buy_production(struct city *pcity)
int city_toggle_worker(struct city *pcity, int city_x, int city_y)
void get_city_dialog_airlift_text(const struct city *pcity, char *buf, size_t bufsz)
int city_change_production(struct city *pcity, struct universal *target)
void city_rotate_specialist(struct city *pcity, int citizen_index)
int get_citydlg_canvas_width(void)
bool canvas_to_city_pos(int *city_x, int *city_y, int city_radius_sq, int canvas_x, int canvas_y)
void get_city_dialog_airlift_value(const struct city *pcity, char *buf, size_t bufsz)
void city_dialog_redraw_map(struct city *pcity, struct canvas *pcanvas)
int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
void get_city_dialog_pollution_text(const struct city *pcity, char *buf, size_t bufsz)
void get_city_dialog_culture_text(const struct city *pcity, char *buf, size_t bufsz)
bool city_can_buy(const struct city *pcity)
int get_citydlg_canvas_height(void)
void get_city_dialog_illness_text(const struct city *pcity, char *buf, size_t bufsz)
void city_report_dialog_update_city(struct city *pcity)
bool client_is_global_observer(void)
bool client_is_observer(void)
struct civclient client
bool can_client_issue_orders(void)
bool client_has_player(void)
#define client_player()
int collect_eventually_buildable_targets(struct universal *targets, struct city *pcity, bool advanced_tech)
Definition climisc.c:818
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:649
cid cid_encode(struct universal target)
Definition climisc.c:482
int collect_already_built_targets(struct universal *targets, struct city *pcity)
Definition climisc.c:912
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:89
#define cid_production
Definition climisc.h:71
int cid
Definition climisc.h:31
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:552
char * incite_cost
Definition comments.c:75
void request_unit_fortify(struct unit *punit)
Definition control.c:2365
void unit_focus_try(struct unit *punit)
Definition control.c:502
void request_unit_change_homecity(struct unit *punit)
Definition control.c:2106
void request_unit_unload(struct unit *pcargo)
Definition control.c:2206
void request_unit_sentry(struct unit *punit)
Definition control.c:2354
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Definition control.c:1941
#define can_unit_do_activity_client(_punit_, _act_)
Definition control.h:41
int counter_index(const struct counter *pcount)
Definition counters.c:174
#define city_counters_iterate_end
Definition counters.h:64
#define city_counters_iterate(pcount)
Definition counters.h:57
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
int int id
Definition editgui_g.h:28
static struct editor_state * editor
Definition editor.c:101
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:846
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:790
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1076
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1097
#define extra_index(_e_)
Definition extras.h:183
int Impr_type_id
Definition fc_types.h:376
#define EC_NONE
Definition fc_types.h:1113
@ TR_SUCCESS
Definition fc_types.h:1246
#define ERM_NONE
Definition fc_types.h:1136
@ O_SHIELD
Definition fc_types.h:101
@ O_FOOD
Definition fc_types.h:101
@ O_TRADE
Definition fc_types.h:101
@ O_SCIENCE
Definition fc_types.h:101
@ O_LUXURY
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
#define N_(String)
Definition fcintl.h:69
const struct ft_color ftc_client
const char * population_to_text(int thousand_citizen)
Definition game.c:734
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct city * game_city_by_number(int id)
Definition game.c:107
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:28
GtkWidget * choice_dialog_start(GtkWindow *parent, const gchar *name, const gchar *text)
void choice_dialog_end(GtkWidget *dshell)
void choice_dialog_add(GtkWidget *dshell, const gchar *label, GCallback handler, gpointer data, bool meta, const gchar *tool_tip)
GtkWidget * citizens_dialog_display(const struct city *pcity)
void citizens_dialog_refresh(const struct city *pcity)
void citizens_dialog_close(const struct city *pcity)
static void unit_sentry_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2876
citydlg_response
Definition citydlg.c:82
@ CDLGR_UNITS
Definition citydlg.c:82
@ CDLGR_PREV
Definition citydlg.c:82
@ CDLGR_NEXT
Definition citydlg.c:82
static int new_dialog_def_page
Definition citydlg.c:219
static void create_and_append_buildings_page(struct city_dialog *pdialog)
Definition citydlg.c:1238
static void unit_upgrade_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2935
static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
Definition citydlg.c:3046
static void city_dialog_update_citizens(struct city_dialog *pdialog)
Definition citydlg.c:1869
static void city_destroy_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3459
static void city_dialog_update_title(struct city_dialog *pdialog)
Definition citydlg.c:1830
static int last_page
Definition citydlg.c:220
static void init_citydlg_dimensions(void)
Definition citydlg.c:332
static void create_and_append_worklist_page(struct city_dialog *pdialog)
Definition citydlg.c:1272
struct tile * loc
Definition citydlg.c:227
@ WORKLIST_PAGE
Definition citydlg.c:112
@ CMA_PAGE
Definition citydlg.c:112
@ HAPPINESS_PAGE
Definition citydlg.c:112
@ SETTINGS_PAGE
Definition citydlg.c:113
@ STICKY_PAGE
Definition citydlg.c:113
@ NUM_PAGES
Definition citydlg.c:114
@ OVERVIEW_PAGE
Definition citydlg.c:112
#define CITY_MAP_MIN_SIZE_X
Definition citydlg.c:128
void real_city_dialog_popup(struct city *pcity)
Definition citydlg.c:566
static void misc_whichtab_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3383
static bool low_citydlg
Definition citydlg.c:230
static struct @141 workertask_req
bool city_dialog_is_open(struct city *pcity)
Definition citydlg.c:587
static void city_dialog_update_building(struct city_dialog *pdialog)
Definition citydlg.c:2069
static void citydlg_response_callback(GtkDialog *dlg, gint response, void *data)
Definition citydlg.c:2502
static void buy_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3174
void real_city_dialog_refresh(struct city *pcity)
Definition citydlg.c:487
static void unit_center_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2775
static struct city_dialog * get_city_dialog(struct city *pcity)
Definition citydlg.c:387
#define CITY_MAP_MIN_SIZE_Y
Definition citydlg.c:129
static void city_dialog_update_information(GtkWidget **info_ebox, GtkWidget **info_label, struct city_dialog *pdialog)
Definition citydlg.c:1932
static GtkWidget * create_citydlg_improvement_list(struct city_dialog *pdialog, GtkWidget *vbox)
Definition citydlg.c:897
static void create_production_header(struct city_dialog *pdialog, GtkContainer *contain)
Definition citydlg.c:1205
static void workertask_dlg_destroy(GtkWidget *w, gpointer data)
Definition citydlg.c:3038
static void city_dialog_update_present_units(struct city_dialog *pdialog)
Definition citydlg.c:2356
#define CITYMAP_SCALE
Definition citydlg.c:76
static gboolean citizens_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2956
static void change_production_callback(GtkComboBox *combo, struct city_dialog *pdialog)
Definition citydlg.c:3237
static void unit_load_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2850
static void set_cityopt_values(struct city_dialog *pdialog)
Definition citydlg.c:3425
static void close_city_dialog(struct city_dialog *pdialog)
Definition citydlg.c:3520
static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:661
static void create_and_append_overview_page(struct city_dialog *pdialog)
Definition citydlg.c:956
static void create_and_append_happiness_page(struct city_dialog *pdialog)
Definition citydlg.c:1316
void popdown_all_city_dialogs(void)
Definition citydlg.c:607
static void buy_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3187
#define dialog_list_iterate_end
Definition citydlg.c:93
static void impr_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition citydlg.c:3310
static void create_and_append_map_page(struct city_dialog *pdialog)
Definition citydlg.c:1144
static void city_dialog_map_create(struct city_dialog *pdialog, struct city_map_canvas *cmap_canvas)
Definition citydlg.c:423
void refresh_unit_city_dialogs(struct unit *punit)
Definition citydlg.c:546
void reset_city_dialogs(void)
Definition citydlg.c:365
static void cityopt_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3391
static void city_dialog_map_recenter(GtkWidget *map_canvas_sw)
Definition citydlg.c:462
static void draw_map_canvas(struct city_dialog *pdialog)
Definition citydlg.c:3162
static bool is_showing_workertask_dialog
Definition citydlg.c:222
#define unit_node_vector_iterate_end
Definition citydlg.c:108
static void sell_callback(struct impr_type *pimprove, gpointer data)
Definition citydlg.c:3256
#define dialog_list_iterate(dialoglist, pdialog)
Definition citydlg.c:91
static void supported_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2802
static void city_dialog_update_prev_next(void)
Definition citydlg.c:2463
static void create_and_append_settings_page(struct city_dialog *pdialog)
Definition citydlg.c:1500
static bool city_dialogs_have_been_initialised
Definition citydlg.c:217
static void close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3451
static struct dialog_list * dialog_list
Definition citydlg.c:216
static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3295
static void create_citydlg_main_map(struct city_dialog *pdialog, GtkWidget *container)
Definition citydlg.c:880
#define NUM_CITIZENS_SHOWN
Definition citydlg.c:110
#define CITYMAP_HEIGHT
Definition citydlg.c:75
static void unit_homecity_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2922
static void unit_fortify_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2889
static void city_dialog_update_counters(struct city_dialog *pdialog)
Definition citydlg.c:1413
static gboolean present_unit_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2598
struct city * owner
Definition citydlg.c:226
static GtkWidget * create_city_info_table(struct city_dialog *pdialog, GtkWidget **info_ebox, GtkWidget **info_label)
Definition citydlg.c:745
static struct city_dialog * create_city_dialog(struct city *pcity)
Definition citydlg.c:1642
static void target_drag_data_received(GtkWidget *w, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time, gpointer user_data)
Definition citydlg.c:1167
static void unit_disband_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2902
#define unit_node_vector_iterate(list, elt)
Definition citydlg.c:106
static void rename_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3349
static void switch_city_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3529
#define CITYMAP_WIDTH
Definition citydlg.c:74
static void city_dialog_update_map(struct city_dialog *pdialog)
Definition citydlg.c:2047
static void create_and_append_counters_page(struct city_dialog *pdialog)
Definition citydlg.c:1393
static void unit_unload_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2863
static void show_units_response(void *data)
Definition citydlg.c:2515
static void initialize_city_dialogs(void)
Definition citydlg.c:341
static int canvas_height
Definition citydlg.c:218
static int canvas_width
Definition citydlg.c:218
#define TINYSCREEN_MAX_HEIGHT
Definition citydlg.c:78
static void city_dialog_update_supported_units(struct city_dialog *pdialog)
Definition citydlg.c:2249
static void unit_activate_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2788
static void present_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2827
@ INFO_LUXURY
Definition citydlg.c:120
@ INFO_STEAL
Definition citydlg.c:122
@ INFO_CORRUPTION
Definition citydlg.c:121
@ NUM_INFO_FIELDS
Definition citydlg.c:123
@ INFO_ILLNESS
Definition citydlg.c:122
@ INFO_WASTE
Definition citydlg.c:121
@ INFO_SIZE
Definition citydlg.c:119
@ INFO_GROWTH
Definition citydlg.c:120
@ INFO_SHIELD
Definition citydlg.c:119
@ INFO_CULTURE
Definition citydlg.c:121
@ INFO_GOLD
Definition citydlg.c:119
@ INFO_SCIENCE
Definition citydlg.c:120
@ INFO_POLLUTION
Definition citydlg.c:121
@ INFO_TRADE
Definition citydlg.c:119
@ INFO_AIRLIFT
Definition citydlg.c:122
@ INFO_GRANARY
Definition citydlg.c:120
@ INFO_FOOD
Definition citydlg.c:119
static void set_city_workertask(GtkWidget *w, gpointer data)
Definition citydlg.c:2983
static void rename_popup_callback(gpointer data, gint response, const char *input)
Definition citydlg.c:3366
static void city_dialog_update_improvement_list(struct city_dialog *pdialog)
Definition citydlg.c:2192
static void create_and_append_cma_page(struct city_dialog *pdialog)
Definition citydlg.c:1480
void popdown_city_dialog(struct city *pcity)
Definition citydlg.c:595
static gboolean supported_unit_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2536
void close_cma_dialog(struct city *pcity)
Definition cma_fe.c:104
struct cma_dialog * create_cma_dialog(struct city *pcity, bool tiny)
Definition cma_fe.c:214
void refresh_cma_dialog(struct city *pcity, enum cma_refresh refresh)
Definition cma_fe.c:471
@ REFRESH_ALL
Definition cma_fe.h:26
void unit_select_dialog_popup(struct tile *ptile)
Definition dialogs.c:377
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1435
void popup_disband_dialog(struct unit_list *punits)
Definition dialogs.c:1473
GtkWidget * toplevel
Definition gui_main.c:125
GtkWidget * map_canvas
Definition gui_main.c:107
int screen_height(void)
Definition gui_main.c:2590
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:32
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:111
void close_happiness_dialog(struct city *pcity)
Definition happiness.c:330
void refresh_happiness_dialog(struct city *pcity)
Definition happiness.c:317
GtkWidget * get_top_happiness_display(struct city *pcity, bool low_dlg, GtkWidget *win)
Definition happiness.c:356
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Definition helpdlg.c:197
GtkWidget * input_dialog_create(GtkWindow *parent, const char *dialogname, const char *text, const char *postinputtest, input_dialog_callback_t response_callback, gpointer response_cli_data)
Definition inputdlg.c:66
static struct gui_dialog * shell
Definition messagedlg.c:39
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
bool request_transport(struct unit *cargo, struct tile *ptile)
void refresh_worklist(GtkWidget *editor)
Definition wldlg.c:1327
void add_worklist_dnd_target(GtkWidget *w)
Definition wldlg.c:339
void reset_city_worklist(GtkWidget *editor, struct city *pcity)
Definition wldlg.c:1279
GtkWidget * create_worklist(void)
Definition wldlg.c:1054
void refresh_all_city_worklists(void)
Definition citydlg.c:3774
@ COUNTERS_PAGE
Definition citydlg.c:115
static void canvas_draw_cb(GtkDrawingArea *w, cairo_t *cr, int width, int height, gpointer data)
Definition citydlg.c:420
static gboolean right_button_down_citymap(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:3285
static gboolean middle_present_unit_release(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:2781
static bool create_unit_menu(struct city_dialog *pdialog, struct unit *punit, GtkWidget *wdg, bool supported)
Definition citydlg.c:2582
static void info_popdown_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:667
static gboolean right_unit_release(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:2827
static gboolean left_button_down_citymap(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:3256
static void close_citydlg_unit_popover(struct city_dialog *pdialog)
Definition citydlg.c:2846
static gboolean middle_supported_unit_release(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:2805
static gboolean citydlg_keyboard_handler(GtkEventControllerKey *controller, guint keyval, guint keycode, GdkModifierType state, gpointer data)
Definition citydlg.c:638
#define menu_item_append_unref(menu, item)
Definition gui_stuff.h:149
void put_unit_picture_city_overlays(struct unit *punit, GtkPicture *p, int height, int *upkeep_cost, int happy_cost)
Definition mapview.c:518
void put_unit_picture(struct unit *punit, GtkPicture *p, int height)
Definition mapview.c:493
void picture_set_from_surface(GtkPicture *pic, cairo_surface_t *surf)
Definition sprite.c:544
static SDL_Surface * info_label
Definition widget.c:57
@ HELP_IMPROVEMENT
Definition helpdlg_g.h:20
@ HELP_WONDER
Definition helpdlg_g.h:21
int impr_sell_gold(const struct impr_type *pimprove)
enum test_result test_player_sell_building_now(struct player *pplayer, struct city *pcity, const struct impr_type *pimprove)
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool is_small_wonder(const struct impr_type *pimprove)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
void center_tile_mapcanvas(const struct tile *ptile)
bool can_slide
#define fc_malloc(sz)
Definition mem.h:34
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:351
bool unit_can_load(const struct unit *punit)
Definition movement.c:915
static const char * name_translation_get(const struct name_translation *ptrans)
#define GUI_GTK4_CITYDLG_MAX_XSIZE
Definition options.h:640
#define GUI_GTK4_CITYDLG_MIN_YSIZE
Definition options.h:643
#define GUI_GTK4_CITYDLG_MIN_XSIZE
Definition options.h:639
#define GUI_GTK4_CITYDLG_MAX_YSIZE
Definition options.h:644
int send_packet_worker_task(struct connection *pc, const struct packet_worker_task *packet)
int dsend_packet_city_options_req(struct connection *pc, int city_id, bv_city_options options, enum city_wl_cancel_behavior wl_cb)
int len
Definition packhand.c:127
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1203
void economy_report_dialog_update(void)
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define FC_INFINITY
Definition shared.h:36
size_t size
Definition specvec.h:72
struct sprite int int int int struct sprite * mask
Definition sprite_g.h:32
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
#define strvec_iterate(psv, str)
#define strvec_iterate_end
cairo_surface_t * surface
Definition canvas.h:23
GtkWidget * prev_command
Definition citydlg.c:208
struct city_dialog::@144 happiness
GtkWidget * name_label
Definition citydlg.c:141
struct city_dialog::@142 overview
GtkWidget * rename_shell
Definition citydlg.c:205
GtkWidget * rename_command
Definition citydlg.c:196
GtkWidget * production_bar
Definition citydlg.c:152
GtkWidget * supported_units_frame
Definition citydlg.c:157
GtkWidget * citizen_pics
Definition citydlg.c:148
GtkWidget * sell_shell
Definition citydlg.c:203
GtkWidget * production_label
Definition citydlg.c:173
GtkWidget * widget
Definition citydlg.c:182
GtkWidget * supported_unit_table
Definition citydlg.c:158
GtkWidget * popover
Definition citydlg.c:147
GtkWidget * disband_on_settler
Definition citydlg.c:198
struct city_map_canvas map_canvas
Definition citydlg.c:150
GtkWidget * improvement_list
Definition citydlg.c:155
GtkWidget * container
Definition citydlg.c:189
GtkWidget * buy_command
Definition citydlg.c:154
short block_signal
Definition citydlg.c:200
GtkWidget * whichtab_radio[NUM_PAGES]
Definition citydlg.c:199
struct unit_node_vector supported_units
Definition citydlg.c:163
cairo_surface_t * map_canvas_store_unscaled
Definition citydlg.c:142
struct city * pcity
Definition citydlg.c:138
struct unit_node_vector present_units
Definition citydlg.c:164
city_map * view
Definition citydlg.h:455
struct city_dialog::@146 misc
GtkWidget * citizens
Definition citydlg.c:185
GtkWidget * show_units_command
Definition citydlg.c:207
Impr_type_id sell_id
Definition citydlg.c:211
GtkWidget * production_combo
Definition citydlg.c:153
GtkBox * container
Definition citydlg.c:189
struct cma_dialog * cma_editor
Definition citydlg.c:193
cairo_surface_t * citizen_surface
Definition citydlg.c:147
struct city_dialog::@145 counters
GtkWidget * shell
Definition citydlg.c:140
GtkWidget * worklist
Definition citydlg.c:176
struct city_dialog::@143 production
GtkWidget * present_units_frame
Definition citydlg.c:160
GtkWidget * info_label[NUM_INFO_FIELDS]
Definition citydlg.c:167
GtkWidget * new_citizens_radio[3]
Definition citydlg.c:197
GtkBox * widget
Definition citydlg.c:190
GtkListStore * change_production_store
Definition citydlg.c:169
GtkWidget * present_unit_table
Definition citydlg.c:161
GtkWidget * notebook
Definition citydlg.c:143
GtkWidget * next_command
Definition citydlg.c:209
GtkTreeSelection * change_selection
Definition citydlg.c:204
enum city_dialog::@189 page
GtkWidget * darea
Definition citydlg.c:134
GtkWidget * sw
Definition citydlg.c:132
Definition city.h:320
struct worker_task_list * task_reqs
Definition city.h:412
int surplus[O_LAST]
Definition city.h:355
enum city_wl_cancel_behavior wlcb
Definition city.h:404
int food_stock
Definition city.h:367
int * counter_values
Definition city.h:408
int pollution
Definition city.h:369
int id
Definition city.h:326
int waste[O_LAST]
Definition city.h:356
struct unit_list * info_units_present
Definition city.h:474
struct player * owner
Definition city.h:323
struct unit_list * info_units_supported
Definition city.h:473
struct worklist worklist
Definition city.h:401
struct universal production
Definition city.h:396
int steal
Definition city.h:414
citizens size
Definition city.h:332
int illness
Definition city.h:434
int culture
Definition city.h:465
int buy_cost
Definition city.h:466
struct tile * tile
Definition city.h:322
int shield_stock
Definition city.h:368
int prod[O_LAST]
Definition city.h:358
struct unit_list * units_supported
Definition city.h:406
struct city::@17::@20 client
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
GtkWidget * shell
Definition cma_fe.h:33
struct city * pcity
Definition cma_fe.h:32
struct player * playing
Definition connection.h:151
Definition climisc.h:82
struct universal item
Definition climisc.h:83
char descr[MAX_LEN_NAME+40]
Definition climisc.h:84
enum unit_activity activity
struct city_list * cities
Definition player.h:279
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int height
Definition citydlg.c:98
GtkWidget * cmd
Definition citydlg.c:96
GtkWidget * pix
Definition citydlg.c:97
GtkEventController * middle
Definition citydlg.c:100
GtkEventController * left
Definition citydlg.c:99
GtkEventController * right
Definition citydlg.c:101
Definition unit.h:137
int upkeep[O_LAST]
Definition unit.h:147
enum unit_activity activity
Definition unit.h:156
int id
Definition unit.h:144
int homecity
Definition unit.h:145
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct tile * ptile
Definition workertask.h:22
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char * unit_description(struct unit *punit)
Definition text.c:481
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:114
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:6794
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:901
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:789
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:937
int tileset_unit_with_upkeep_height(const struct tileset *t)
Definition tilespec.c:859
struct sprite * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Definition tilespec.c:6733
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:6816
const struct unit_type * utype
Definition fc_types.h:721
const struct impr_type * building
Definition fc_types.h:714
bool can_unit_change_homecity_to(const struct civ_map *nmap, const struct unit *punit, const struct city *pcity)
Definition unit.c:473
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2449
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:367
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:760
#define unit_tile(_pu)
Definition unit.h:396
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1703
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66