Freeciv-3.4
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-5.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 "update_queue.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 *buy_command;
157
158 GtkWidget *supported_units_frame;
159 GtkWidget *supported_unit_table;
160
161 GtkWidget *present_units_frame;
162 GtkWidget *present_unit_table;
163
164 struct unit_node_vector supported_units;
165 struct unit_node_vector present_units;
166
168
172
173 struct {
174 GtkWidget *production_label;
175 GtkWidget *production_bar;
176 GtkWidget *buy_command;
179
180 struct {
182
187
188 struct {
190 GtkBox *widget;
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);
321 guint position,
323 gpointer data);
324
325static void sell_callback(const struct impr_type *pimprove, gpointer data);
326static void sell_callback_response(GtkWidget *w, gint response, gpointer data);
327
328static void impr_callback(GtkColumnView *self, guint position,
329 gpointer data);
330
331static void rename_callback(GtkWidget * w, gpointer data);
332static void rename_popup_callback(gpointer data, gint response,
333 const char *input);
334static void set_cityopt_values(struct city_dialog *pdialog);
335static void cityopt_callback(GtkWidget * w, gpointer data);
336static void misc_whichtab_callback(GtkWidget * w, gpointer data);
337
338static void city_destroy_callback(GtkWidget *w, gpointer data);
339static void close_city_dialog(struct city_dialog *pdialog);
340static void citydlg_response_callback(GtkDialog *dlg, gint response,
341 void *data);
342static void close_callback(GtkWidget *w, gpointer data);
343static void switch_city_callback(GtkWidget *w, gpointer data);
344
345#define FC_TYPE_IMPR_ROW (fc_impr_row_get_type())
346
348
360
365
367
368#define IMPR_ROW_PIXBUF 0
369#define IMPR_ROW_DESC 1
370#define IMPR_ROW_UPKEEP 2
371
372#define FC_TYPE_PROD_ROW (fc_prod_row_get_type())
373
375
385
390
392
393#define PROD_ROW_PIXBUF 0
394#define PROD_ROW_NAME 1
395
396/**********************************************************************/
400{
402
403 if (row->sprite != nullptr) {
404 g_object_unref(G_OBJECT(row->sprite));
405 row->sprite = nullptr;
406 }
407
409}
410
411/**********************************************************************/
414static void
421
422/**********************************************************************/
425static void
427{
428 self->sprite = nullptr;
429}
430
431/**********************************************************************/
435{
436 FcImprRow *result;
437
438 result = g_object_new(FC_TYPE_IMPR_ROW, nullptr);
439
440 return result;
441}
442
443/**********************************************************************/
447{
449
450 if (row->sprite != nullptr) {
451 g_object_unref(G_OBJECT(row->sprite));
452 row->sprite = nullptr;
453 }
454
456}
457
458/**********************************************************************/
461static void
468
469/**********************************************************************/
472static void
474{
475 self->sprite = nullptr;
476}
477
478/**********************************************************************/
482{
483 FcProdRow *result;
484
485 result = g_object_new(FC_TYPE_PROD_ROW, nullptr);
486
487 return result;
488}
489
490/***********************************************************************/
499
500/***********************************************************************/
503static void initialize_city_dialogs(void)
504{
505 int height;
506
508
512
513 /* Use default layout when height cannot be determined
514 * (when height == 0) */
515 if (height > 0 && height <= TINYSCREEN_MAX_HEIGHT) {
517 } else {
519 }
520
522}
523
524/***********************************************************************/
528{
530 return;
531 }
532
534
536 /* There's no reasonable way to resize a GtkImage, so we don't try.
537 Instead we just redraw the overview within the existing area.
538 The player has to close and reopen the dialog to fix this. */
539 city_dialog_update_map(pdialog);
541
543}
544
545/***********************************************************************/
549static struct city_dialog *get_city_dialog(struct city *pcity)
550{
553 }
554
556 if (pdialog->pcity == pcity) {
557 return pdialog;
558 }
560
561 return NULL;
562}
563
564/***********************************************************************/
568 int width, int height, gpointer data)
569{
570 struct city_dialog *pdialog = data;
571
574 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
575 cairo_paint_with_alpha(cr, 0.5);
576 } else {
577 cairo_paint(cr);
578 }
579}
580
581/***********************************************************************/
584static void city_dialog_map_create(struct city_dialog *pdialog,
586{
587 GtkWidget *sw, *darea;
590
599
600 darea = gtk_drawing_area_new();
603 canvas_draw_cb, pdialog, NULL);
604
606 g_signal_connect(controller, "pressed",
612 g_signal_connect(controller, "pressed",
616
617 /* save all widgets for the city map */
618 cmap_canvas->sw = sw;
619 cmap_canvas->darea = darea;
620}
621
622/***********************************************************************/
646
647/***********************************************************************/
651{
652 struct city_dialog *pdialog = get_city_dialog(pcity);
653
654 log_debug("CITYMAP_WIDTH: %d", CITYMAP_WIDTH);
655 log_debug("CITYMAP_HEIGHT: %d", CITYMAP_HEIGHT);
656 log_debug("CITYMAP_SCALE: %.3f", CITYMAP_SCALE);
657
661 }
662
663 if (!pdialog) {
664 return;
665 }
666
671 city_dialog_update_map(pdialog);
676
679
681
682 if (!low_citydlg) {
684 }
688 }
689
690 if (!client_is_observer()) {
692 }
693
697 } else {
698 /* Set the buttons we do not want live while a Diplomat investigates */
700 }
701}
702
703/***********************************************************************/
708{
709 struct city *pcity_sup, *pcity_pre;
710 struct city_dialog *pdialog;
711
714
715 if (pcity_sup && (pdialog = get_city_dialog(pcity_sup))) {
717 }
718
719 if (pcity_pre && (pdialog = get_city_dialog(pcity_pre))) {
721 }
722}
723
724/***********************************************************************/
728{
729 struct city_dialog *pdialog;
730
731 if (!(pdialog = get_city_dialog(pcity))) {
732 pdialog = create_city_dialog(pcity);
733 }
734
736
737 /* center the city map(s); this must be *after* the city dialog was drawn
738 * else the size information is missing! */
740 if (pdialog->happiness.map_canvas.sw) {
742 }
743}
744
745/***********************************************************************/
749{
750 return get_city_dialog(pcity) != NULL;
751}
752
753/***********************************************************************/
757{
758 struct city_dialog *pdialog = get_city_dialog(pcity);
759
760 if (pdialog) {
761 close_city_dialog(pdialog);
762 }
763}
764
765/***********************************************************************/
781
782/***********************************************************************/
788 GdkModifierType state,
789 gpointer data)
790{
791 struct city_dialog *pdialog = (struct city_dialog *)data;
792
793 if (state & GDK_CONTROL_MASK) {
794 switch (keyval) {
795 case GDK_KEY_Left:
797 return TRUE;
798
799 case GDK_KEY_Right:
801 return TRUE;
802
803 default:
804 break;
805 }
806 }
807
808 return FALSE;
809}
810
811/**********************************************************************/
815{
817}
818
819/***********************************************************************/
823 double x, double y, gpointer data)
824{
826 struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
827 GtkWidget *p, *label;
828 char buf[1024];
829
830 switch (GPOINTER_TO_UINT(data)) {
831 case INFO_SIZE:
832 fc_snprintf(buf, sizeof(buf), _("Population: %d, Specialists: %d"),
833 pdialog->pcity->size, city_specialists(pdialog->pcity));
834 break;
835 case INFO_FOOD:
836 get_city_dialog_output_text(pdialog->pcity, O_FOOD, buf, sizeof(buf));
837 break;
838 case INFO_SHIELD:
840 buf, sizeof(buf));
841 break;
842 case INFO_TRADE:
843 get_city_dialog_output_text(pdialog->pcity, O_TRADE, buf, sizeof(buf));
844 break;
845 case INFO_GOLD:
846 get_city_dialog_output_text(pdialog->pcity, O_GOLD, buf, sizeof(buf));
847 break;
848 case INFO_SCIENCE:
850 buf, sizeof(buf));
851 break;
852 case INFO_LUXURY:
854 buf, sizeof(buf));
855 break;
856 case INFO_CULTURE:
857 get_city_dialog_culture_text(pdialog->pcity, buf, sizeof(buf));
858 break;
859 case INFO_POLLUTION:
860 get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
861 break;
862 case INFO_ILLNESS:
863 get_city_dialog_illness_text(pdialog->pcity, buf, sizeof(buf));
864 break;
865 case INFO_AIRLIFT:
866 get_city_dialog_airlift_text(pdialog->pcity, buf, sizeof(buf));
867 break;
868 default:
869 return TRUE;
870 }
871
872 p = gtk_popover_new();
873
875
876 label = gtk_label_new(buf);
877 gtk_widget_set_name(label, "city_label");
882
884
885 g_signal_connect(p, "closed",
887
889
890 return TRUE;
891}
892
893/***********************************************************************/
899{
900 int i;
901 GtkWidget *table, *label;
902
903 static const char *output_label[NUM_INFO_FIELDS] = {
904 N_("Size:"),
905 N_("Food:"),
906 N_("Prod:"),
907 N_("Trade:"),
908 N_("Gold:"),
909 N_("Luxury:"),
910 N_("Science:"),
911 N_("Granary:"),
912 N_("Change in:"),
913 N_("Corruption:"),
914 N_("Waste:"),
915 N_("Culture:"),
916 N_("Pollution:"),
917 N_("Plague risk:"),
918 N_("Tech Stolen:"),
919 N_("Airlift:"),
920 };
921 static bool output_label_done;
923
929
931
932 for (i = 0; i < NUM_INFO_FIELDS; i++) {
933 label = gtk_label_new(output_label[i]);
934 switch (i) {
935 case INFO_SIZE:
936 case INFO_TRADE:
937 case INFO_SCIENCE:
938 case INFO_GROWTH:
940 break;
941
942 case INFO_FOOD:
943 case INFO_GOLD:
944 case INFO_GRANARY:
945 case INFO_CORRUPTION:
947 break;
948 default:
949 break;
950 }
952 gtk_widget_set_name(label, "city_label"); /* For font style? */
955 gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
956
957 label = gtk_label_new("");
958 switch (i) {
959 case INFO_TRADE:
960 case INFO_SCIENCE:
961 case INFO_GROWTH:
963 break;
964
965 case INFO_GOLD:
966 case INFO_GRANARY:
967 case INFO_CORRUPTION:
969 break;
970 default:
971 break;
972 }
973
974 g_object_set_data(G_OBJECT(label), "pdialog", pdialog);
975
977 g_signal_connect(controller, "pressed",
980
981 info_label[i] = label;
982 gtk_widget_set_name(label, "city_label"); /* Ditto */
985
986 gtk_grid_attach(GTK_GRID(table), label, 1, i, 1, 1);
987 }
988
989 /*
990 * Allow special highlighting of emergencies for granary etc by
991 * city_dialog_update_information().
992 */
993 {
994 /* This will persist, and can be shared between overview and happiness
995 * pages. */
997
998 if (emergency_provider == NULL) {
1000
1002 ".emergency {\n"
1003 " color: rgba(255, 0.0, 0.0, 255);\n"
1004 "}",
1005 -1);
1006
1011 }
1012 }
1013
1015
1016 return table;
1017}
1018
1019/***********************************************************************/
1024static void create_citydlg_main_map(struct city_dialog *pdialog,
1025 GtkWidget *grid, int col, int row)
1026{
1027 GtkWidget *frame;
1028
1029 frame = gtk_frame_new(_("City map"));
1032 gtk_grid_attach(GTK_GRID(grid), frame, col, row, 1, 1);
1033
1034 city_dialog_map_create(pdialog, &pdialog->overview.map_canvas);
1036}
1037
1038/**********************************************************************/
1043 gpointer user_data)
1044{
1045 FcImprRow *row;
1047
1049
1050 switch (GPOINTER_TO_INT(user_data)) {
1051 case IMPR_ROW_PIXBUF:
1052 gtk_image_set_from_pixbuf(GTK_IMAGE(child), row->sprite);
1053 break;
1054 case IMPR_ROW_DESC:
1055 {
1056 gtk_label_set_text(GTK_LABEL(child), row->description);
1057
1058 if (row->redundant) {
1061
1065
1067 }
1068 }
1069 break;
1070 case IMPR_ROW_UPKEEP:
1071 {
1072 char buf[256];
1073
1074 fc_snprintf(buf, sizeof(buf), "%d", row->upkeep);
1076 }
1077 break;
1078 }
1079}
1080
1081/**********************************************************************/
1086 gpointer user_data)
1087{
1088 switch (GPOINTER_TO_INT(user_data)) {
1089 case IMPR_ROW_PIXBUF:
1091 break;
1092 case IMPR_ROW_DESC:
1093 case IMPR_ROW_UPKEEP:
1095 break;
1096 }
1097}
1098
1099/**********************************************************************/
1105 gpointer data)
1106{
1108
1109 if (rnum >= 0) {
1111
1112 if (row != nullptr && row->tooltip != nullptr) {
1114
1115 return TRUE;
1116 }
1117 }
1118
1119 return FALSE;
1120}
1121
1122/***********************************************************************/
1126{
1127 GtkWidget *list;
1130 GtkSingleSelection *selection;
1131
1132 /* Improvements */
1134
1137
1143
1146
1152
1153 column = gtk_column_view_column_new(_("Description"), factory);
1155
1161
1164
1165 g_object_set(list, "has-tooltip", TRUE, nullptr);
1166 g_signal_connect(list, "query-tooltip",
1168
1169 g_signal_connect(list, "activate",
1170 G_CALLBACK(impr_callback), pdialog);
1171
1172 return list;
1173}
1174
1175/**********************************************************************/
1180 gpointer user_data)
1181{
1182 FcProdRow *row;
1184
1186
1187 switch (GPOINTER_TO_INT(user_data)) {
1188 case PROD_ROW_PIXBUF:
1189 gtk_image_set_from_pixbuf(GTK_IMAGE(child), row->sprite);
1190 break;
1191 case PROD_ROW_NAME:
1192 {
1193 gtk_label_set_text(GTK_LABEL(child), row->name);
1194
1195 if (row->useless) {
1198
1202
1204 }
1205 }
1206 break;
1207 }
1208}
1209
1210/**********************************************************************/
1215 gpointer user_data)
1216{
1217 switch (GPOINTER_TO_INT(user_data)) {
1218 case PROD_ROW_PIXBUF:
1220 break;
1221 case PROD_ROW_NAME:
1223 break;
1224 }
1225}
1226
1227/***********************************************************************/
1244{
1246 GtkWidget *right, *frame, *table;
1247 GtkWidget *label, *sw, *view, *bar, *vp;
1248 /* TRANS: Overview tab in city dialog */
1249 const char *tab_title = _("_Overview");
1251 int page_row = 0;
1252
1253 /* Main page */
1254 page = gtk_grid_new();
1263
1264 if (!low_citydlg) {
1266 GtkWidget *list;
1268 GtkWidget *middle;
1269 GtkWidget *vbox;
1270 GtkWidget *hbox;
1271 int middle_col = 0;
1272
1273 /* Middle: city map, improvements */
1274 middle = gtk_grid_new();
1276 gtk_grid_attach(GTK_GRID(page), middle, 0, page_row++, 1, 1);
1277
1278 /* City map */
1279 create_citydlg_main_map(pdialog, middle, middle_col++, 0);
1280
1281 /* Improvements */
1283 gtk_grid_attach(GTK_GRID(middle), vbox, middle_col++, 0, 1, 1);
1284
1286
1287 label = g_object_new(GTK_TYPE_LABEL, "label", _("Production:"),
1288 "xalign", 0.0, "yalign", 0.5, NULL);
1289 gtk_box_append(GTK_BOX(vbox), label);
1290
1292 gtk_box_append(GTK_BOX(vbox), hbox);
1293
1295
1299
1305
1308
1314
1317
1318 bar = gtk_progress_bar_new();
1320 pdialog->overview.production_bar = bar;
1322
1323 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1324
1326
1327 g_signal_connect(pdialog->overview.change_prod_selection, "selection-changed",
1329
1330 pdialog->overview.buy_command
1331 = icon_label_button_new("system-run", _("_Buy"));
1333 g_signal_connect(pdialog->overview.buy_command, "clicked",
1334 G_CALLBACK(buy_callback), pdialog);
1335
1336 label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
1337 "mnemonic-widget", view,
1338 "label", _("I_mprovements:"),
1339 "xalign", 0.0, "yalign", 0.5, NULL);
1340 gtk_box_append(GTK_BOX(vbox), label);
1341 gtk_box_append(GTK_BOX(vbox), view);
1342 } else {
1343 pdialog->overview.buy_command = NULL;
1344 pdialog->overview.production_bar = NULL;
1345 pdialog->overview.change_prod_store = nullptr;
1346 pdialog->overview.change_prod_selection = nullptr;
1347 }
1348
1349 /* Bottom: info, units */
1352
1353 /* Info */
1354 frame = gtk_frame_new(_("Info"));
1355 gtk_box_append(GTK_BOX(bottom), frame);
1356
1357 table = create_city_info_table(pdialog,
1358 pdialog->overview.info_label);
1362
1363 /* Right: present and supported units (overview page) */
1365 gtk_box_append(GTK_BOX(bottom), right);
1366
1371
1372 /* Supported units */
1379 sw);
1380
1381
1388
1391
1392 /* Present units */
1399
1406
1409
1410 /* Show page */
1412}
1413
1414/***********************************************************************/
1417static void create_and_append_map_page(struct city_dialog *pdialog)
1418{
1419 if (low_citydlg) {
1420 GtkWidget *page;
1421 GtkWidget *label;
1422 const char *tab_title = _("Citymap");
1423 int page_row = 0;
1424
1425 page = gtk_grid_new();
1434
1435 create_citydlg_main_map(pdialog, page, 0, page_row++);
1436
1438 }
1439}
1440
1441/***********************************************************************/
1445 const GValue *value,
1446 double x, double y, gpointer data)
1447{
1448 struct city_dialog *pdialog = (struct city_dialog *) data;
1449 cid id;
1450 struct universal univ;
1451
1452 if (NULL != client.conn.playing
1453 && city_owner(pdialog->pcity) != client.conn.playing) {
1454 return FALSE;
1455 }
1456
1457 id = g_value_get_int(value);
1458 univ = cid_production(id);
1459
1460 city_change_production(pdialog->pcity, &univ);
1461
1462 return TRUE;
1463}
1464
1465/***********************************************************************/
1469static int create_production_header(struct city_dialog *pdialog,
1470 GtkWidget *grid, int row)
1471{
1472 GtkWidget *hgrid, *bar;
1473 int grid_col = 0;
1474
1475 hgrid = gtk_grid_new();
1481 gtk_grid_attach(GTK_GRID(grid), hgrid, 0, row++, 1, 1);
1482
1483 /* The label is set in city_dialog_update_building() */
1484 bar = gtk_progress_bar_new();
1487 pdialog->production.production_bar = bar;
1488 gtk_grid_attach(GTK_GRID(hgrid), bar, grid_col++, 0, 1, 1);
1489 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1490
1492
1493 pdialog->production.buy_command
1494 = icon_label_button_new("system-run", _("_Buy"));
1496 grid_col++, 0, 1, 1);
1497
1498 g_signal_connect(pdialog->production.buy_command, "clicked",
1499 G_CALLBACK(buy_callback), pdialog);
1500
1501 return row;
1502}
1503
1504/***********************************************************************/
1508{
1509 if (low_citydlg) {
1510 GtkWidget *page;
1511 GtkWidget *label;
1512 GtkWidget *vbox;
1513 GtkWidget *view;
1514 const char *tab_title = _("Buildings");
1515 int page_row = 0;
1516
1517 page = gtk_grid_new();
1525
1526 page_row = create_production_header(pdialog, page, page_row);
1527 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1528
1530 gtk_grid_attach(GTK_GRID(page), vbox, 0, page_row++, 1, 1);
1531
1533
1534 gtk_box_append(GTK_BOX(vbox), view);
1535
1537 }
1538}
1539
1540/***********************************************************************/
1544{
1545 const char *tab_title = _("P_roduction");
1547 GtkWidget *page, *editor;
1548 int page_row = 0;
1549
1550 page = gtk_grid_new();
1557 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1558
1559 /* Stuff that's being currently built */
1560 if (!low_citydlg) {
1562 "label", _("Production:"),
1563 "xalign", 0.0, "yalign", 0.5, NULL);
1564 pdialog->production.production_label = label;
1565 gtk_grid_attach(GTK_GRID(page), label, 0, page_row++, 1, 1);
1566
1567 page_row = create_production_header(pdialog, page, page_row);
1568 } else {
1569 pdialog->production.production_label = NULL;
1570 }
1571
1577 reset_city_worklist(editor, pdialog->pcity);
1578 gtk_grid_attach(GTK_GRID(page), editor, 0, page_row++, 1, 1);
1579 pdialog->production.worklist = editor;
1580
1582}
1583
1584/***********************************************************************/
1595{
1596 GtkWidget *page, *label, *table, *right, *left, *frame;
1597 const char *tab_title = _("Happ_iness");
1598 int page_col = 0;
1599 int left_row = 0;
1600
1601 /* Main page */
1602 page = gtk_grid_new();
1609 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1610
1611 /* Left: info, citizens */
1612 left = gtk_grid_new();
1615 gtk_grid_attach(GTK_GRID(page), left, page_col++, 0, 1, 1);
1616
1617 if (!low_citydlg) {
1618 /* Upper left: info */
1619 frame = gtk_frame_new(_("Info"));
1620 gtk_grid_attach(GTK_GRID(left), frame, 0, left_row++, 1, 1);
1621
1622 table = create_city_info_table(pdialog,
1623 pdialog->happiness.info_label);
1626 }
1627
1628 /* Lower left: citizens */
1632 0, left_row++, 1, 1);
1634 citizens_dialog_display(pdialog->pcity));
1635 }
1636
1637 /* Right: city map, happiness */
1639 gtk_grid_attach(GTK_GRID(page), right, page_col++, 0, 1, 1);
1640
1641 if (!low_citydlg) {
1642 /* Upper right: city map */
1643 frame = gtk_frame_new(_("City map"));
1646 gtk_box_append(GTK_BOX(right), frame);
1647
1648 city_dialog_map_create(pdialog, &pdialog->happiness.map_canvas);
1650 }
1651
1652 /* Lower right: happiness */
1654 gtk_box_append(GTK_BOX(right), pdialog->happiness.widget);
1657 pdialog->shell));
1658
1659 /* Show page */
1661}
1662
1663/**********************************************************************/
1666/**********************************************************************/
1671{
1673 GtkLabel *label = GTK_LABEL(gtk_label_new(_("Counters")));
1674
1675 pdialog->counters.container = NULL;
1676 pdialog->counters.widget = NULL;
1677
1679
1681
1683
1684 gtk_widget_show(page);
1685}
1686
1687/***********************************************************************/
1690static void create_and_append_cma_page(struct city_dialog *pdialog)
1691{
1692 GtkWidget *page, *label;
1693 const char *tab_title = _("_Governor");
1694
1696
1698
1699 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1700
1701 pdialog->cma_editor = create_cma_dialog(pdialog->pcity, low_citydlg);
1702 gtk_box_append(GTK_BOX(page), pdialog->cma_editor->shell);
1703
1705}
1706
1707/***********************************************************************/
1711{
1712 int i;
1713 GtkWidget *vgrid, *page, *frame, *label, *button;
1715 GtkWidget *group;
1716 const char *tab_title = _("_Settings");
1717 int grid_row = 0;
1718
1719 static const char *new_citizens_output_label[] = {
1720 N_("Luxury"),
1721 N_("Science"),
1722 N_("Gold")
1723 };
1724
1725 static const char *disband_label
1726 = N_("Allow unit production to disband city");
1727
1728 static const char *misc_whichtab_label[NUM_PAGES] = {
1729 N_("Overview page"),
1730 N_("Production page"),
1731 N_("Happiness page"),
1732 N_("Counters Page"),
1733 N_("Governor page"),
1734 N_("This Settings page"),
1735 N_("Last active page")
1736 };
1737
1738 static bool new_citizens_label_done;
1739 static bool misc_whichtab_label_done;
1740
1741 /* Initialize signal_blocker */
1742 pdialog->misc.block_signal = 0;
1743
1744
1745 page = gtk_grid_new();
1751
1753
1755
1756 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1757
1758 /* new_citizens radio */
1759 frame = gtk_frame_new(_("New citizens produce"));
1760 gtk_grid_attach(GTK_GRID(page), frame, 0, 0, 1, 1);
1762
1763 vgrid = gtk_grid_new();
1767
1770
1771 group = NULL;
1772 for (i = 0; i < ARRAY_SIZE(new_citizens_output_label); i++) {
1775 GTK_CHECK_BUTTON(group));
1776 pdialog->misc.new_citizens_radio[i] = button;
1777 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1778 g_signal_connect(button, "toggled",
1779 G_CALLBACK(cityopt_callback), pdialog);
1780 group = button;
1781 }
1782
1783 /* Next is the next-time-open radio group in the right column */
1784 frame = gtk_frame_new(_("Next time open"));
1785 gtk_grid_attach(GTK_GRID(page), frame, 1, 0, 1, 1);
1787
1788 vgrid = gtk_grid_new();
1789 grid_row = 0;
1793
1796
1797 group = NULL;
1798 for (i = 0; i < ARRAY_SIZE(misc_whichtab_label); i++) {
1801 GTK_CHECK_BUTTON(group));
1802 pdialog->misc.whichtab_radio[i] = button;
1803 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1804 g_signal_connect(button, "toggled",
1806 group = button;
1807 }
1808
1809 /* Now we go back and fill the hbox rename */
1810 frame = gtk_frame_new(_("City"));
1811 gtk_widget_set_margin_top(frame, 12);
1813 gtk_grid_attach(GTK_GRID(page), frame, 0, 1, 1, 1);
1814
1815 vgrid = gtk_grid_new();
1816 grid_row = 0;
1820
1821 button = gtk_button_new_with_mnemonic(_("R_ename..."));
1822 pdialog->misc.rename_command = button;
1823 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1824 g_signal_connect(button, "clicked",
1825 G_CALLBACK(rename_callback), pdialog);
1826
1828
1829 /* The disband-city-on-unit-production button */
1831 pdialog->misc.disband_on_settler = button;
1832 gtk_grid_attach(GTK_GRID(vgrid), button, 0, grid_row++, 1, 1);
1833 g_signal_connect(button, "toggled",
1834 G_CALLBACK(cityopt_callback), pdialog);
1835
1836 /* We choose which page to popup by default */
1838 (pdialog->
1840 TRUE);
1841
1842 set_cityopt_values(pdialog);
1843
1845
1846 if (new_dialog_def_page == (NUM_PAGES - 1)) {
1848 last_page);
1849 } else {
1852 }
1853}
1854
1855/***********************************************************************/
1864{
1865 struct city_dialog *pdialog;
1867 GtkWidget *vbox, *hbox, *cbox;
1870 int ccol = 0;
1872 struct player *owner;
1873
1876 }
1877
1878 pdialog = fc_malloc(sizeof(struct city_dialog));
1879 pdialog->pcity = pcity;
1880 pdialog->sell_shell = NULL;
1881 pdialog->rename_shell = NULL;
1882 pdialog->happiness.map_canvas.sw = NULL; /* Make sure NULL if spy */
1883 pdialog->happiness.map_canvas.darea = NULL; /* Ditto */
1884 pdialog->happiness.citizens = NULL; /* Ditto */
1885 pdialog->counters.widget = NULL;
1886 pdialog->counters.container = NULL;
1887 pdialog->production.buy_command = NULL;
1888 pdialog->production.production_label = NULL;
1889 pdialog->production.production_bar = NULL;
1890 pdialog->cma_editor = NULL;
1894
1895 pdialog->shell = gtk_dialog_new();
1897 setup_dialog(pdialog->shell, toplevel);
1898
1899 g_signal_connect(pdialog->shell, "destroy",
1901 gtk_widget_set_name(pdialog->shell, "Freeciv");
1902
1903 gtk_widget_realize(pdialog->shell);
1904
1905 /* Keep the icon of the executable on Windows (see PR#36491) */
1906#ifndef FREECIV_MSWINDOWS
1907 {
1908 gtk_window_set_icon_name(GTK_WINDOW(pdialog->shell), "citydlg");
1909 }
1910#endif /* FREECIV_MSWINDOWS */
1911
1912 /* Restore size of the city dialog. */
1916
1917 pdialog->popover = NULL;
1918
1922 gtk_box_append(GTK_BOX(vbox), hbox);
1923
1924 /**** Citizens bar here ****/
1925 cbox = gtk_grid_new();
1926 gtk_box_append(GTK_BOX(hbox), cbox);
1927
1930
1934 pdialog->citizen_pics = gtk_picture_new();
1935
1944 gtk_grid_attach(GTK_GRID(cbox), pdialog->citizen_pics, ccol++, 0, 1, 1);
1945
1947 g_signal_connect(controller, "pressed",
1948 G_CALLBACK(citizens_callback), pdialog);
1950
1951 /**** City name label here ****/
1952 pdialog->name_label = gtk_label_new(NULL);
1957
1958 /**** -Start of Notebook- ****/
1959
1960 pdialog->notebook = gtk_notebook_new();
1963 gtk_box_append(GTK_BOX(vbox), pdialog->notebook);
1964
1968
1970
1971 /* Only create these tabs if not a spy */
1975 }
1976
1978
1979 if (owner == client_player()
1980 && !client_is_observer()) {
1983 } else {
1986 }
1987
1988 /**** End of Notebook ****/
1989
1990 /* Bottom buttons */
1991
1992 pdialog->show_units_command =
1993 gtk_dialog_add_button(GTK_DIALOG(pdialog->shell), _("_List present units..."), CDLGR_UNITS);
1994
1995 g_signal_connect(GTK_DIALOG(pdialog->shell), "response",
1997
1998 pdialog->prev_command = gtk_button_new_from_icon_name("go-previous");
2000 GTK_WIDGET(pdialog->prev_command), 1);
2001
2002 pdialog->next_command = gtk_button_new_from_icon_name("go-next");
2004 GTK_WIDGET(pdialog->next_command), 2);
2005
2006 if (owner != client_player()) {
2009 }
2010
2012 _("_Close"), GTK_RESPONSE_CLOSE);
2013
2016
2018 G_CALLBACK(close_callback), pdialog);
2019
2020 g_signal_connect(pdialog->prev_command, "clicked",
2022
2023 g_signal_connect(pdialog->next_command, "clicked",
2025
2026 /* Some other things we gotta do */
2027
2029 g_signal_connect(controller, "key-pressed",
2032
2034
2036
2037 /* Need to do this every time a new dialog is opened. */
2039
2041
2043
2044 return pdialog;
2045}
2046
2047/**************** Functions to update parts of the dialog *****************/
2048
2049/***********************************************************************/
2052static void city_dialog_update_title(struct city_dialog *pdialog)
2053{
2054 gchar *buf;
2055 const gchar *now;
2056
2057 if (city_unhappy(pdialog->pcity)) {
2058 /* TRANS: city dialog title */
2059 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - DISORDER"),
2060 city_name_getx(pdialog->pcity),
2062 } else if (city_celebrating(pdialog->pcity)) {
2063 /* TRANS: city dialog title */
2064 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - celebrating"),
2065 city_name_getx(pdialog->pcity),
2067 } else if (city_happy(pdialog->pcity)) {
2068 /* TRANS: city dialog title */
2069 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - happy"),
2070 city_name_getx(pdialog->pcity),
2072 } else {
2073 /* TRANS: city dialog title */
2074 buf = g_strdup_printf(_("<b>%s</b> - %s citizens"),
2075 city_name_getx(pdialog->pcity),
2077 }
2078
2080 if (strcmp(now, buf) != 0) {
2083 }
2084
2085 g_free(buf);
2086}
2087
2088/***********************************************************************/
2091static void city_dialog_update_citizens(struct city_dialog *pdialog)
2092{
2093 enum citizen_category categories[MAX_CITY_SIZE];
2096 struct city *pcity = pdialog->pcity;
2098 int num_supers
2100 ARRAY_SIZE(categories) - num_citizens,
2101 &categories[num_citizens]);
2102 cairo_t *cr;
2103
2104 if (num_supers >= 0) {
2105 /* Just draw superspecialists in the common roster */
2107 } else {
2108 /* FIXME: show them in some compact way */
2109 num_citizens = ARRAY_SIZE(categories);
2110 }
2111 /* If there is not enough space we stack the icons. We draw from left to */
2112 /* right. width is how far we go to the right for each drawn pixmap. The */
2113 /* last icon is always drawn in full, and so has reserved */
2114 /* tileset_small_sprite_width(tileset) pixels. */
2115
2117 if (num_citizens > 1) {
2119 / (num_citizens - 1));
2120 } else {
2121 width = full_width;
2122 }
2123 pdialog->cwidth = width;
2124
2125 /* overview page */
2126 /* keep these values in sync with create_city_dialog */
2129
2130 cr = cairo_create(pdialog->citizen_surface);
2131
2132 for (i = 0; i < num_citizens; i++) {
2134 get_citizen_sprite(tileset, categories[i], i, pcity)->surface,
2135 i * width, 0);
2136 cairo_rectangle(cr, i * width, 0,
2137 /* Always draw last citizen in full */
2138 i + 1 < num_citizens ? width : full_width,
2140 cairo_fill(cr);
2141 }
2142
2143 total_used_width = (i - 1) * width + full_width;
2144
2146 /* Clear the rest of the area.
2147 * Note that this might still be necessary even in cases where
2148 * num_citizens > NUM_CITIZENS_SHOWN, if the available width cannot be
2149 * divided perfectly. */
2154 cairo_fill(cr);
2155 }
2156
2157 cairo_destroy(cr);
2158
2160 pdialog->citizen_surface);
2161
2163}
2164
2165
2166/**********************************************************************/
2169static void city_dialog_update_counters(struct city_dialog *pdialog)
2170{
2175 char int_val[101];
2176 char *text;
2177 int text_size;
2178
2179 if (NULL != pdialog->counters.widget) {
2181 GTK_WIDGET(pdialog->counters.widget));
2182 }
2183
2184 if (NULL == pdialog->counters.container) {
2186 }
2187
2191
2195 counterValue = GTK_LABEL(gtk_label_new(_("Current value is: ")));
2197 fc_snprintf(int_val, sizeof(int_val), "%d", pdialog->pcity->counter_values[counter_index(pcount)]);
2201
2203 counterValue = GTK_LABEL(gtk_label_new(_("Activated once value equal or higher than: ")));
2205 fc_snprintf(int_val, sizeof(int_val), "%d", pcount->checkpoint);
2209
2210 text_size = 0;
2211 if (NULL != pcount->helptext) {
2212 strvec_iterate(pcount->helptext, text_) {
2215 }
2216 if (0 < text_size) {
2217 text = malloc(text_size+1);
2218 text_size = 0;
2219 strvec_iterate(pcount->helptext, text_) {
2220 strcpy(&text[text_size], text_);
2224 free(text);
2226 }
2229
2232}
2233
2234/***********************************************************************/
2238 struct city_dialog *pdialog)
2239{
2240 int i, illness = 0;
2241 char buf[NUM_INFO_FIELDS][512];
2242 struct city *pcity = pdialog->pcity;
2243 int granaryturns;
2246
2247 /* fill the buffers with the necessary info */
2248 if (supers) {
2249 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d+%d)",
2250 pcity->size, non_workers, supers);
2251 } else if (non_workers) {
2252 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
2253 pcity->size, non_workers);
2254 } else {
2255 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d", pcity->size);
2256 }
2257 fc_snprintf(buf[INFO_FOOD], sizeof(buf[INFO_FOOD]), "%3d (%+4d)",
2258 pcity->prod[O_FOOD], pcity->surplus[O_FOOD]);
2259 fc_snprintf(buf[INFO_SHIELD], sizeof(buf[INFO_SHIELD]), "%3d (%+4d)",
2260 pcity->prod[O_SHIELD] + pcity->waste[O_SHIELD],
2261 pcity->surplus[O_SHIELD]);
2262 fc_snprintf(buf[INFO_TRADE], sizeof(buf[INFO_TRADE]), "%3d (%+4d)",
2263 pcity->surplus[O_TRADE] + pcity->waste[O_TRADE],
2264 pcity->surplus[O_TRADE]);
2265 fc_snprintf(buf[INFO_GOLD], sizeof(buf[INFO_GOLD]), "%3d (%+4d)",
2266 pcity->prod[O_GOLD], pcity->surplus[O_GOLD]);
2267 fc_snprintf(buf[INFO_LUXURY], sizeof(buf[INFO_LUXURY]), "%3d",
2268 pcity->prod[O_LUXURY]);
2269 fc_snprintf(buf[INFO_SCIENCE], sizeof(buf[INFO_SCIENCE]), "%3d",
2270 pcity->prod[O_SCIENCE]);
2271 fc_snprintf(buf[INFO_GRANARY], sizeof(buf[INFO_GRANARY]), "%4d/%-4d",
2273
2275 if (granaryturns == 0) {
2276 /* TRANS: city growth is blocked. Keep short. */
2277 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("blocked"));
2278 } else if (granaryturns == FC_INFINITY) {
2279 /* TRANS: city is not growing. Keep short. */
2280 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("never"));
2281 } else {
2282 /* A negative value means we'll have famine in that many turns.
2283 But that's handled down below. */
2284 /* TRANS: city growth turns. Keep short. */
2286 PL_("%d turn", "%d turns", abs(granaryturns)),
2287 abs(granaryturns));
2288 }
2290 pcity->waste[O_TRADE]);
2291 fc_snprintf(buf[INFO_WASTE], sizeof(buf[INFO_WASTE]), "%4d",
2292 pcity->waste[O_SHIELD]);
2293 fc_snprintf(buf[INFO_CULTURE], sizeof(buf[INFO_CULTURE]), "%4d",
2294 pcity->client.culture);
2296 pcity->pollution);
2297 if (!game.info.illness_on) {
2298 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), " -.-");
2299 } else {
2301 /* illness is in tenth of percent */
2302 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), "%5.1f%%",
2303 (float)illness / 10.0);
2304 }
2305 if (pcity->steal) {
2306 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), PL_("%d time", "%d times", pcity->steal),
2307 pcity->steal);
2308 } else {
2309 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), _("Not stolen"));
2310 }
2311
2313
2314 /* stick 'em in the labels */
2315 for (i = 0; i < NUM_INFO_FIELDS; i++) {
2317 }
2318
2319 /*
2320 * Make use of the emergency-indicating styles set up for certain labels
2321 * in create_city_info_table().
2322 */
2323 /* For starvation, the "4" below is arbitrary. 3 turns should be enough
2324 * of a warning. */
2325 if (granaryturns > -4 && granaryturns < 0) {
2327 } else {
2329 }
2330
2331 if (granaryturns == 0 || pcity->surplus[O_FOOD] < 0) {
2333 } else {
2335 }
2336
2337 /* Someone could add the color &orange for better granularity here */
2338 if (pcity->pollution >= 10) {
2340 } else {
2342 }
2343
2344 /* Illness is in tenth of percent, i.e 100 == 10.0% */
2345 if (illness >= 100) {
2347 } else {
2349 }
2350}
2351
2352/***********************************************************************/
2355static void city_dialog_update_map(struct city_dialog *pdialog)
2356{
2357 struct canvas store = FC_STATIC_CANVAS_INIT;
2358
2359 store.surface = pdialog->map_canvas_store_unscaled;
2360
2361 /* The drawing is done in three steps.
2362 * 1. First we render to a pixmap with the appropriate canvas size.
2363 * 2. Then the pixmap is rendered into a pixbuf of equal size.
2364 * 3. Finally this pixbuf is composited and scaled onto the GtkImage's
2365 * target pixbuf.
2366 */
2367
2368 city_dialog_redraw_map(pdialog->pcity, &store);
2369
2370 /* draw to real window */
2371 draw_map_canvas(pdialog);
2372}
2373
2374/***********************************************************************/
2377static void city_dialog_update_building(struct city_dialog *pdialog)
2378{
2379 char buf[32], buf2[200];
2380 gdouble pct;
2381 GListStore *store;
2382 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2383 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2384 int targets_used, item;
2385 struct city *pcity = pdialog->pcity;
2387 const char *descr = city_production_name_translation(pcity);
2389
2390 if (pdialog->overview.buy_command != NULL) {
2392 }
2393 if (pdialog->production.buy_command != NULL) {
2395 }
2396
2397 /* Make sure build slots info is up to date */
2398 if (pdialog->production.production_label != NULL) {
2400
2401 /* Only display extra info if more than one slot is available */
2402 if (build_slots > 1) {
2403 fc_snprintf(buf2, sizeof(buf2),
2404 /* TRANS: never actually used with built_slots <= 1 */
2405 PL_("Production (up to %d unit per turn):",
2406 "Production (up to %d units per turn):", build_slots),
2407 build_slots);
2410 } else {
2412 GTK_LABEL(pdialog->production.production_label), _("Production:"));
2413 }
2414 }
2415
2416 /* Update what the city is working on */
2418
2419 if (cost > 0) {
2420 pct = (gdouble) pcity->shield_stock / (gdouble) cost;
2421 pct = CLAMP(pct, 0.0, 1.0);
2422 } else {
2423 pct = 1.0;
2424 }
2425
2426 if (pdialog->overview.production_bar != NULL) {
2427 fc_snprintf(buf2, sizeof(buf2), "%s%s\n%s", descr,
2428 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2433 }
2434
2435 if (pdialog->production.production_bar != NULL) {
2436 fc_snprintf(buf2, sizeof(buf2), "%s%s: %s", descr,
2437 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2442 }
2443
2444 store = pdialog->overview.change_prod_store;
2445 if (store != nullptr) {
2446 int cur = -1;
2447 int actcount = 0;
2448
2449 if (pdialog->overview.change_prod_selection != nullptr) {
2451 -1, TRUE);
2452 }
2453
2455
2457 = collect_eventually_buildable_targets(targets, pdialog->pcity, FALSE);
2458 name_and_sort_items(targets, targets_used, items, FALSE, pcity);
2459
2460 for (item = 0; item < targets_used; item++) {
2461 if (can_city_build_now(&(wld.map), pcity, &items[item].item,
2462 RPT_CERTAIN)) {
2463 const char *name;
2464 struct sprite *sprite;
2465 GdkPixbuf *pix;
2466 struct universal *target = &items[item].item;
2467 bool useless;
2469
2470 if (VUT_UTYPE == target->kind) {
2474 useless = FALSE;
2475 } else {
2478 useless = is_improvement_redundant(pcity, target->value.building);
2479 }
2481
2482 row->name = name;
2483 row->id = (gint)cid_encode(items[item].item);
2484 row->sprite = pix;
2485 row->useless = useless;
2486
2487 g_list_store_append(store, row);
2489
2490 if (are_universals_equal(target, &pcity->production)) {
2491 cur = actcount;
2492 }
2493
2494 actcount++;
2495 }
2496 }
2497
2498 if (pdialog->overview.change_prod_selection != nullptr) {
2500 cur, TRUE);
2501 }
2502 }
2503}
2504
2505/***********************************************************************/
2509{
2510 int item, targets_used;
2511 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2512 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2513
2514 const char *tooltip_sellable = _("Press <b>ENTER</b> or double-click to "
2515 "sell an improvement.");
2516 const char *tooltip_great_wonder = _("Great Wonder - cannot be sold.");
2517 const char *tooltip_small_wonder = _("Small Wonder - cannot be sold.");
2518
2520 name_and_sort_items(targets, targets_used, items, FALSE, pdialog->pcity);
2521
2523
2524 for (item = 0; item < targets_used; item++) {
2525 GdkPixbuf *pix;
2526 int upkeep;
2527 struct sprite *sprite;
2528 struct universal target = items[item].item;
2530
2531 fc_assert_action(VUT_IMPROVEMENT == target.kind, continue);
2532 /* This takes effects (like Adam Smith's) into account. */
2533 upkeep = city_improvement_upkeep(pdialog->pcity, target.value.building);
2535
2537
2538 row->impr = target.value.building;
2539 row->sprite = pix;
2540 row->description = items[item].descr;
2541 row->upkeep = upkeep;
2542 row->redundant = is_improvement_redundant(pdialog->pcity,
2543 target.value.building);
2544 row->tooltip = is_great_wonder(target.value.building) ?
2546 (is_small_wonder(target.value.building) ?
2548
2551 }
2552}
2553
2554/***********************************************************************/
2558{
2559 struct unit_list *units;
2560 struct unit_node_vector *nodes;
2561 int n, m, i;
2562 gchar *buf;
2564 const struct civ_map *nmap = &(wld.map);
2565
2566 if (NULL != client.conn.playing
2567 && city_owner(pdialog->pcity) != client.conn.playing) {
2568 units = pdialog->pcity->client.info_units_supported;
2569 } else {
2570 units = pdialog->pcity->units_supported;
2571 }
2572
2573 nodes = &pdialog->overview.supported_units;
2574
2575 n = unit_list_size(units);
2576 m = unit_node_vector_size(nodes);
2577
2578 if (m > n) {
2579 i = 0;
2581 if (i++ >= n) {
2583 elt->cmd);
2584 }
2586
2588 } else {
2589 for (i = m; i < n; i++) {
2590 GtkWidget *cmd, *pix;
2591 struct unit_node node;
2592
2593 cmd = gtk_button_new();
2594 node.cmd = cmd;
2595
2597
2598 pix = gtk_picture_new();
2599 node.pix = pix;
2601
2603
2605 cmd);
2606
2607 node.left = NULL;
2608 node.middle = NULL;
2609 node.right = NULL;
2610
2611 unit_node_vector_append(nodes, node);
2612 }
2613 }
2614
2615 i = 0;
2616 unit_list_iterate(units, punit) {
2617 struct unit_node *pnode;
2618 int happy_cost = city_unit_unhappiness(nmap, punit, &free_unhappy);
2619
2620 pnode = unit_node_vector_get(nodes, i);
2621 if (pnode) {
2622 GtkWidget *cmd, *pix;
2625
2626 cmd = pnode->cmd;
2627 pix = pnode->pix;
2628
2630 punit->upkeep, happy_cost);
2631
2632 if (pnode->left != NULL) {
2636 }
2637
2639
2641 g_signal_connect(controller, "pressed",
2645 pnode->left = controller;
2649 g_signal_connect(controller, "released",
2653 pnode->middle = controller;
2657 g_signal_connect(controller, "released",
2661 pnode->right = controller;
2662
2663 if (city_owner(pdialog->pcity) != client.conn.playing) {
2665 } else {
2667 }
2668
2671 }
2672 i++;
2674
2675 buf = g_strdup_printf(_("Supported units %d"), n);
2677 g_free(buf);
2678}
2679
2680/***********************************************************************/
2684{
2685 struct unit_list *units;
2686 struct unit_node_vector *nodes;
2687 int n, m, i;
2688 gchar *buf;
2689
2690 if (NULL != client.conn.playing
2691 && city_owner(pdialog->pcity) != client.conn.playing) {
2692 units = pdialog->pcity->client.info_units_present;
2693 } else {
2694 units = pdialog->pcity->tile->units;
2695 }
2696
2697 nodes = &pdialog->overview.present_units;
2698
2699 n = unit_list_size(units);
2700 m = unit_node_vector_size(nodes);
2701
2702 if (m > n) {
2703 i = 0;
2705 if (i++ >= n) {
2707 elt->cmd);
2708 }
2710
2712 } else {
2713 for (i = m; i < n; i++) {
2714 GtkWidget *cmd, *pix;
2715 struct unit_node node;
2716
2717 cmd = gtk_button_new();
2718 node.cmd = cmd;
2719
2721
2722 pix = gtk_picture_new();
2723 node.pix = pix;
2725
2727
2729 cmd);
2730
2731 node.left = NULL;
2732 node.middle = NULL;
2733 node.right = NULL;
2734
2735 unit_node_vector_append(nodes, node);
2736 }
2737 }
2738
2739 i = 0;
2740 unit_list_iterate(units, punit) {
2741 struct unit_node *pnode;
2742
2743 pnode = unit_node_vector_get(nodes, i);
2744 if (pnode) {
2745 GtkWidget *cmd, *pix;
2748
2749 cmd = pnode->cmd;
2750 pix = pnode->pix;
2751
2753
2754 if (pnode->left != NULL) {
2758 }
2759
2761
2763 g_signal_connect(controller, "pressed",
2767 pnode->left = controller;
2771 g_signal_connect(controller, "released",
2775 pnode->middle = controller;
2779 g_signal_connect(controller, "released",
2783 pnode->right = controller;
2784
2785 if (city_owner(pdialog->pcity) != client.conn.playing) {
2787 } else {
2789 }
2790
2793 }
2794 i++;
2796
2797 buf = g_strdup_printf(_("Present units %d"), n);
2799 g_free(buf);
2800}
2801
2802/***********************************************************************/
2810{
2811 int count = 0;
2812 int city_number;
2813
2814 if (NULL != client.conn.playing) {
2816 } else {
2817 city_number = FC_INFINITY; /* ? */
2818 }
2819
2820 /* The first time, we see if all the city dialogs are open */
2822 if (city_owner(pdialog->pcity) == client.conn.playing) {
2823 count++;
2824 }
2826
2827 if (count == city_number) { /* All are open, shouldn't prev/next */
2829 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), FALSE);
2830 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), FALSE);
2832 } else {
2834 if (city_owner(pdialog->pcity) == client.conn.playing) {
2835 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), TRUE);
2836 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), TRUE);
2837 }
2839 }
2840}
2841
2842/***********************************************************************/
2845static void citydlg_response_callback(GtkDialog *dlg, gint response,
2846 void *data)
2847{
2848 switch (response) {
2849 case CDLGR_UNITS:
2850 show_units_response(data);
2851 break;
2852 }
2853}
2854
2855/***********************************************************************/
2858static void show_units_response(void *data)
2859{
2860 struct city_dialog *pdialog = (struct city_dialog *) data;
2861 struct tile *ptile = pdialog->pcity->tile;
2862
2863 if (unit_list_size(ptile->units)) {
2865 }
2866}
2867
2868/***********************************************************************/
2878static bool create_unit_menu(struct city_dialog *pdialog, struct unit *punit,
2879 GtkWidget *wdg, bool supported)
2880{
2881 GMenu *menu;
2882 GActionGroup *group;
2883 GSimpleAction *act;
2884
2885 if (!can_client_issue_orders()) {
2886 return FALSE;
2887 }
2888
2889 if (pdialog->popover != NULL) {
2891 }
2892
2894 menu = g_menu_new();
2895
2896 if (supported) {
2897 act = g_simple_action_new("center", NULL);
2898 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2902 menu_item_append_unref(menu, g_menu_item_new(_("Cen_ter"), "win.center"));
2903 }
2904
2905 act = g_simple_action_new("activate", NULL);
2906 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2910 menu_item_append_unref(menu, g_menu_item_new(_("_Activate unit"),
2911 "win.activate"));
2912
2913 act = g_simple_action_new("activate_close", NULL);
2914 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2916
2917 if (supported) {
2918 g_signal_connect(act, "activate",
2921 } else {
2922 g_signal_connect(act, "activate",
2925 }
2926
2928 g_menu_item_new(_("Activate unit, _close dialog"),
2929 "win.activate_close"));
2930
2931 if (!supported) {
2932 act = g_simple_action_new("load", NULL);
2933 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2938 menu_item_append_unref(menu, g_menu_item_new(_("_Load unit"), "win.load"));
2939
2940 act = g_simple_action_new("unload", NULL);
2941 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2949 unit_tile(punit)));
2950 menu_item_append_unref(menu, g_menu_item_new(_("_Unload unit"),
2951 "win.unload"));
2952
2953 act = g_simple_action_new("sentry", NULL);
2954 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2962 menu_item_append_unref(menu, g_menu_item_new(_("_Sentry unit"),
2963 "win.sentry"));
2964
2965 act = g_simple_action_new("fortify", NULL);
2966 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2974 menu_item_append_unref(menu, g_menu_item_new(_("_Fortify unit"),
2975 "win.fortify"));
2976 }
2977
2978 act = g_simple_action_new("disband", NULL);
2979 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2985 menu_item_append_unref(menu, g_menu_item_new(_("_Disband unit"),
2986 "win.disband"));
2987
2988 if (!supported) {
2989 act = g_simple_action_new("rehome", NULL);
2990 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
2996 pdialog->pcity));
2999 "win.rehome"));
3000
3001 act = g_simple_action_new("upgrade", NULL);
3002 g_object_set_data(G_OBJECT(act), "dlg", pdialog);
3011 != NULL);
3012 menu_item_append_unref(menu, g_menu_item_new(_("U_pgrade unit"),
3013 "win.upgrade"));
3014 }
3015
3017 g_object_ref(pdialog->popover);
3018 gtk_widget_insert_action_group(pdialog->popover, "win", group);
3020
3021
3023
3024 return TRUE;
3025}
3026
3027/***********************************************************************/
3031 double x, double y, gpointer data)
3032{
3033 struct city_dialog *pdialog;
3034 struct city *pcity;
3035 struct unit *punit =
3036 player_unit_by_number(client_player(), (size_t) data);
3037
3038 if (NULL != punit
3040 && NULL != (pdialog = get_city_dialog(pcity))) {
3041
3042 return create_unit_menu(pdialog, punit,
3044 TRUE);
3045 }
3046
3047 return TRUE;
3048}
3049
3050/***********************************************************************/
3054 double x, double y, gpointer data)
3055{
3056 struct city_dialog *pdialog;
3057 struct city *pcity;
3058 struct unit *punit =
3059 player_unit_by_number(client_player(), (size_t) data);
3060
3061 if (NULL != punit
3062 && NULL != (pcity = tile_city(unit_tile(punit)))
3063 && NULL != (pdialog = get_city_dialog(pcity))) {
3064
3065 return create_unit_menu(pdialog, punit,
3067 FALSE);
3068 }
3069
3070 return TRUE;
3071}
3072
3073/***********************************************************************/
3078 int n_press, double x, double y,
3079 gpointer data)
3080{
3081 struct city_dialog *pdialog;
3082 struct city *pcity;
3083 struct unit *punit =
3084 player_unit_by_number(client_player(), (size_t) data);
3085
3086 if (NULL != punit
3087 && NULL != (pcity = tile_city(unit_tile(punit)))
3088 && NULL != (pdialog = get_city_dialog(pcity))
3091 close_city_dialog(pdialog);
3092 }
3093
3094 return TRUE;
3095}
3096
3097/***********************************************************************/
3102 double x, double y, gpointer data)
3103{
3104 struct city_dialog *pdialog;
3105 struct city *pcity;
3106 struct unit *punit =
3107 player_unit_by_number(client_player(), (size_t) data);
3108
3109 if (NULL != punit
3111 && NULL != (pdialog = get_city_dialog(pcity))
3114 close_city_dialog(pdialog);
3115 }
3116
3117 return TRUE;
3118}
3119
3120/***********************************************************************/
3124 double x, double y, gpointer data)
3125{
3126 struct unit *punit =
3127 player_unit_by_number(client_player(), (size_t) data);
3128
3129 if (NULL != punit
3132 }
3133
3134 return TRUE;
3135}
3136
3137/***********************************************************************/
3142static void close_citydlg_unit_popover(struct city_dialog *pdialog)
3143{
3144 if (pdialog->popover != NULL) {
3145 gtk_widget_unparent(pdialog->popover);
3146 g_object_unref(pdialog->popover);
3147 pdialog->popover = NULL;
3148 }
3149}
3150
3151/***********************************************************************/
3155 gpointer data)
3156{
3157 struct unit *punit =
3159
3160 if (NULL != punit) {
3162 }
3163
3165}
3166
3167/***********************************************************************/
3171 gpointer data)
3172{
3173 struct unit *punit =
3175
3176 if (NULL != punit) {
3177 /* FIXME: If unit is not idle to begin with, we can only request
3178 * idling, and as we have no server reply yet,
3179 * the unit_focus_try() below will fail. */
3182 }
3183
3185}
3186
3187/***********************************************************************/
3192 GVariant *parameter,
3193 gpointer data)
3194{
3195 struct unit *punit =
3197
3198 if (NULL != punit) {
3199 struct city *pcity =
3201
3202 /* FIXME: If unit is not idle to begin with, we can only request
3203 * idling, and as we have no server reply yet,
3204 * the unit_focus_try() below will fail. */
3207
3208 if (NULL != pcity) {
3209 struct city_dialog *pdialog = get_city_dialog(pcity);
3210
3211 if (NULL != pdialog) {
3212 close_city_dialog(pdialog);
3213 }
3214 }
3215 }
3216
3218}
3219
3220/***********************************************************************/
3225 GVariant *parameter,
3226 gpointer data)
3227{
3228 struct unit *punit =
3230
3231 if (NULL != punit) {
3232 struct city *pcity = tile_city(unit_tile(punit));
3233
3234 /* FIXME: If unit is not idle to begin with, we can only request
3235 * idling, and as we have no server reply yet,
3236 * the unit_focus_try() below will fail. */
3239
3240 if (NULL != pcity) {
3241 struct city_dialog *pdialog = get_city_dialog(pcity);
3242
3243 if (NULL != pdialog) {
3244 close_city_dialog(pdialog);
3245 }
3246 }
3247 }
3248
3250}
3251
3252/***********************************************************************/
3256 gpointer data)
3257{
3258 struct unit *punit =
3260
3261 if (NULL != punit) {
3263 }
3264
3266}
3267
3268/***********************************************************************/
3272 gpointer data)
3273{
3274 struct unit *punit =
3276
3277 if (NULL != punit) {
3279 }
3280
3282}
3283
3284/***********************************************************************/
3288 gpointer data)
3289{
3290 struct unit *punit =
3292
3293 if (NULL != punit) {
3295 }
3296
3298}
3299
3300/***********************************************************************/
3304 gpointer data)
3305{
3306 struct unit *punit =
3308
3309 if (NULL != punit) {
3311 }
3312
3314}
3315
3316/***********************************************************************/
3320 gpointer data)
3321{
3322 struct unit_list *punits;
3323 struct unit *punit =
3325
3326 if (NULL == punit) {
3327 return;
3328 }
3329
3334
3336}
3337
3338/***********************************************************************/
3343 gpointer data)
3344{
3345 struct unit *punit =
3347
3348 if (NULL != punit) {
3350 }
3351
3353}
3354
3355/***********************************************************************/
3359 gpointer data)
3360{
3361 struct unit_list *punits;
3362 struct unit *punit =
3364
3365 if (NULL == punit) {
3366 return;
3367 }
3368
3373
3375}
3376
3377/******** Callbacks for citizen bar, map funcs that are not update ********/
3378
3379/***********************************************************************/
3384 double x, double y, gpointer data)
3385{
3386 struct city_dialog *pdialog = data;
3387 struct city *pcity = pdialog->pcity;
3388 int citnum, tlen, len;
3389
3390 if (!can_client_issue_orders()) {
3391 return FALSE;
3392 }
3393
3395 len = (city_size_get(pcity) - 1) * pdialog->cwidth + tlen;
3396
3397 if (x > len) {
3398 /* No citizen that far to the right */
3399 return FALSE;
3400 }
3401 citnum = MIN(city_size_get(pcity) - 1, x / pdialog->cwidth);
3402
3404
3405 return TRUE;
3406}
3407
3408/***********************************************************************/
3412{
3413 enum unit_activity act = (enum unit_activity)GPOINTER_TO_INT(data);
3414 struct city *pcity = workertask_req.owner;
3415 struct tile *ptile = workertask_req.loc;
3416 struct packet_worker_task task;
3417
3418 task.city_id = pcity->id;
3419
3420 if (act == ACTIVITY_LAST) {
3421 task.tgt = -1;
3422 task.want = 0;
3423 } else {
3424 enum extra_cause cause = activity_to_extra_cause(act);
3426 struct extra_type *tgt;
3427
3428 if (cause != EC_NONE) {
3429 tgt = next_extra_for_tile(ptile, cause, city_owner(pcity), NULL);
3430 } else if (rmcause != ERM_NONE) {
3432 } else {
3433 tgt = NULL;
3434 }
3435
3436 if (tgt == NULL) {
3437 struct terrain *pterr = tile_terrain(ptile);
3438
3439 if ((act != ACTIVITY_TRANSFORM
3440 || pterr->transform_result == NULL || pterr->transform_result == pterr)
3441 && (act != ACTIVITY_CULTIVATE || pterr->cultivate_result == NULL)
3442 && (act != ACTIVITY_PLANT || pterr->plant_result == NULL)) {
3443 /* No extra to order */
3444 output_window_append(ftc_client, _("There's no suitable extra to order."));
3445
3446 return;
3447 }
3448
3449 task.tgt = -1;
3450 } else {
3451 task.tgt = extra_index(tgt);
3452 }
3453
3454 task.want = 100;
3455 }
3456
3457 task.tile_id = ptile->index;
3458 task.activity = act;
3459
3461}
3462
3463/***********************************************************************/
3470
3471/***********************************************************************/
3474static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
3475{
3477 GtkWidget *shl;
3478 struct terrain *pterr = tile_terrain(ptile);
3479 struct universal for_terr = { .kind = VUT_TERRAIN,
3480 .value = { .terrain = pterr }};
3481 struct worker_task *ptask;
3482
3484 workertask_req.owner = pcity;
3485 workertask_req.loc = ptile;
3486
3488 _("What Action to Request"),
3489 _("Select autoworker activity:"));
3490
3491 ptask = worker_task_list_get(pcity->task_reqs, 0);
3492 if (ptask != NULL) {
3493 choice_dialog_add(shl, _("Clear request"),
3496 }
3497
3499 choice_dialog_add(shl, Q_("?act:Mine"),
3502 }
3503 if (pterr->plant_result != NULL
3505 NULL, &for_terr)) {
3506 choice_dialog_add(shl, _("Plant"),
3509 }
3511 choice_dialog_add(shl, _("Irrigate"),
3514 }
3515 if (pterr->cultivate_result != NULL
3517 NULL, &for_terr)) {
3518 choice_dialog_add(shl, _("Cultivate"),
3521 }
3523 choice_dialog_add(shl, _("Road"),
3526 }
3527 if (pterr->transform_result != pterr && pterr->transform_result != NULL
3529 NULL, &for_terr)) {
3530 choice_dialog_add(shl, _("Transform"),
3533 }
3535 city_owner(pcity), NULL) != NULL) {
3536 choice_dialog_add(shl, _("Clean"),
3539 }
3540
3541 choice_dialog_add(shl, _("_Cancel"), 0, 0, FALSE, NULL);
3543
3545 NULL);
3546 }
3547}
3548
3549/***********************************************************************/
3553 double x, double y, gpointer data)
3554{
3555 struct city_dialog *pdialog = data;
3557
3558 if (!can_client_issue_orders()) {
3559 return FALSE;
3560 }
3561
3562 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
3563 return FALSE;
3564 }
3565
3568
3570 city_map_radius_sq_get(pdialog->pcity),
3571 canvas_x, canvas_y)) {
3573 }
3574
3575 return TRUE;
3576}
3577
3578/***********************************************************************/
3582 double x, double y, gpointer data)
3583{
3584 struct city_dialog *pdialog = data;
3586
3587 if (!can_client_issue_orders()) {
3588 return FALSE;
3589 }
3590
3593
3595 city_map_radius_sq_get(pdialog->pcity),
3596 canvas_x, canvas_y)) {
3597 struct city *pcity = pdialog->pcity;
3598
3599 popup_workertask_dlg(pdialog->pcity,
3602 city_x, city_y));
3603 }
3604
3605 return TRUE;
3606}
3607
3608/***********************************************************************/
3611static void draw_map_canvas(struct city_dialog *pdialog)
3612{
3614 if (pdialog->happiness.map_canvas.darea) { /* in case of spy */
3616 }
3617}
3618
3619/************** Callbacks for Buy, Change, Sell, Worklist *****************/
3620
3621/***********************************************************************/
3624static void buy_callback_response(GObject *dialog, GAsyncResult *result,
3625 gpointer data)
3626{
3628 result, NULL);
3629
3630 if (button == 0) {
3631 struct city_dialog *pdialog = data;
3632
3633 city_buy_production(pdialog->pcity);
3634 }
3635}
3636
3637/***********************************************************************/
3640static void buy_callback(GtkWidget *w, gpointer data)
3641{
3643 struct city_dialog *pdialog = data;
3644 const char *name = city_production_name_translation(pdialog->pcity);
3645 int value = pdialog->pcity->client.buy_cost;
3646 char buf[1024];
3647
3648 if (!can_client_issue_orders()) {
3649 return;
3650 }
3651
3652 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
3653 "Treasury contains %d gold.",
3654 client_player()->economic.gold),
3655 client_player()->economic.gold);
3656
3657 if (value <= client_player()->economic.gold) {
3658 const char *buttons[] = { _("Yes"), _("No"), NULL };
3659
3661 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3662 PL_("Buy %s for %d gold?\n%s",
3663 "Buy %s for %d gold?\n%s", value),
3664 name, value, buf);
3666 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3668
3670 buy_callback_response, pdialog);
3671 } else {
3672 const char *buttons[] = { _("Close"), NULL };
3673
3675 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3676 PL_("%s costs %d gold.\n%s",
3677 "%s costs %d gold.\n%s", value),
3678 name, value, buf);
3680 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3683 }
3684}
3685
3686/***********************************************************************/
3690 guint position,
3691 guint n_items,
3692 gpointer data)
3693{
3697 struct universal univ = cid_production(row->id);
3698
3699 city_change_production(((struct city_dialog *)data)->pcity, &univ);
3700 }
3701}
3702
3703/***********************************************************************/
3706static void sell_callback(const struct impr_type *pimprove, gpointer data)
3707{
3708 GtkWidget *shl;
3709 struct city_dialog *pdialog = (struct city_dialog *) data;
3710 pdialog->sell_id = improvement_number(pimprove);
3711 int price;
3712
3713 if (!can_client_issue_orders()) {
3714 return;
3715 }
3716
3718 pimprove) != TR_SUCCESS) {
3719 return;
3720 }
3721
3722 price = impr_sell_gold(pimprove);
3727 PL_("Sell %s for %d gold?",
3728 "Sell %s for %d gold?", price),
3729 city_improvement_name_translation(pdialog->pcity, pimprove), price);
3730 setup_dialog(shl, pdialog->shell);
3731 pdialog->sell_shell = shl;
3732
3733 gtk_window_set_title(GTK_WINDOW(shl), _("Sell It!"));
3734
3735 g_signal_connect(shl, "response",
3737
3739}
3740
3741/***********************************************************************/
3744static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
3745{
3746 struct city_dialog *pdialog = data;
3747
3748 if (response == GTK_RESPONSE_YES) {
3749 city_sell_improvement(pdialog->pcity, pdialog->sell_id);
3750 }
3752
3753 pdialog->sell_shell = NULL;
3754}
3755
3756/***********************************************************************/
3759static void impr_callback(GtkColumnView *self, guint position,
3760 gpointer data)
3761{
3762 GdkSeat *seat;
3764 GListStore *store = ((struct city_dialog *)data)->overview.improvement_list;
3765 FcImprRow *row = g_list_model_get_item(G_LIST_MODEL(store), position);
3766 const struct impr_type *pimpr = row->impr;
3767 GtkWidget *wdg = ((struct city_dialog *)data)->shell;
3768
3771
3772 if (!(mask & GDK_CONTROL_MASK)) {
3773 sell_callback(pimpr, data);
3774 } else {
3775 if (is_great_wonder(pimpr)) {
3777 } else {
3779 }
3780 }
3781}
3782
3783/************ Callbacks for stuff on the Misc. Settings page **************/
3784
3785/***********************************************************************/
3789{
3790 struct city_dialog *pdialog;
3791
3792 pdialog = (struct city_dialog *) data;
3793
3794 pdialog->rename_shell = input_dialog_create(GTK_WINDOW(pdialog->shell),
3795 /* "shellrenamecity" */
3796 _("Rename City"),
3797 _("What should we rename the city to?"),
3798 city_name_get(pdialog->pcity),
3799 rename_popup_callback, pdialog);
3800}
3801
3802/***********************************************************************/
3805static void rename_popup_callback(gpointer data, gint response,
3806 const char *input)
3807{
3808 struct city_dialog *pdialog = data;
3809
3810 if (pdialog) {
3811 if (response == GTK_RESPONSE_OK) {
3812 city_rename(pdialog->pcity, input);
3813 } /* else CANCEL or DELETE_EVENT */
3814
3815 pdialog->rename_shell = NULL;
3816 }
3817}
3818
3819/***********************************************************************/
3823{
3825}
3826
3827/***********************************************************************/
3831{
3832 struct city_dialog *pdialog = (struct city_dialog *) data;
3833
3834 if (!can_client_issue_orders()) {
3835 return;
3836 }
3837
3838 if (!pdialog->misc.block_signal) {
3839 struct city *pcity = pdialog->pcity;
3841
3842 fc_assert(CITYO_LAST == 3);
3843
3847 }
3850 }
3853 }
3854
3856 pcity->wlcb);
3857 }
3858}
3859
3860/***********************************************************************/
3885
3886/******************** Callbacks for: Close, Prev, Next. *******************/
3887
3888/***********************************************************************/
3891static void close_callback(GtkWidget *w, gpointer data)
3892{
3893 close_city_dialog((struct city_dialog *) data);
3894}
3895
3896/***********************************************************************/
3900{
3901 struct city_dialog *pdialog;
3902 int width, height;
3903
3904 /* Save size of the city dialog. */
3906
3907 pdialog = (struct city_dialog *) data;
3909
3911 citizens_dialog_close(pdialog->pcity);
3912 }
3913 close_happiness_dialog(pdialog->pcity);
3914 close_cma_dialog(pdialog->pcity);
3915
3916 /* Save size of the city dialog. */
3919 width,
3923 height,
3925
3926 last_page
3928
3931
3934
3935 if (pdialog->sell_shell) {
3937 }
3938 if (pdialog->rename_shell) {
3940 }
3941
3944
3945 free(pdialog);
3946
3947 /* Need to do this every time a new dialog is closed. */
3949}
3950
3951/***********************************************************************/
3954static void close_city_dialog(struct city_dialog *pdialog)
3955{
3957}
3958
3959/***********************************************************************/
3964{
3965 struct city_dialog *pdialog = (struct city_dialog *) data;
3966 int i, j, dir, size;
3967 struct city *new_pcity = NULL;
3968
3970 return;
3971 }
3972
3974
3976 fc_assert_ret(size >= 1);
3978
3979 if (size == 1) {
3980 return;
3981 }
3982
3983 /* dir = 1 will advance to the city, dir = -1 will get previous */
3984 if (w == GTK_WIDGET(pdialog->next_command)) {
3985 dir = 1;
3986 } else if (w == GTK_WIDGET(pdialog->prev_command)) {
3987 dir = -1;
3988 } else {
3989 /* Always fails. */
3991 || w == GTK_WIDGET(pdialog->prev_command));
3992 dir = 1;
3993 }
3994
3995 for (i = 0; i < size; i++) {
3996 if (pdialog->pcity == city_list_get(client.conn.playing->cities, i)) {
3997 break;
3998 }
3999 }
4000
4001 fc_assert_ret(i < size);
4002
4003 for (j = 1; j < size; j++) {
4005 (i + dir * j + size) % size);
4007
4008 fc_assert_ret(other_pdialog != pdialog);
4009 if (!other_pdialog) {
4011 break;
4012 }
4013 }
4014
4015 if (!new_pcity) {
4016 /* Every other city has an open city dialog. */
4017 return;
4018 }
4019
4020 /* cleanup happiness dialog */
4022 citizens_dialog_close(pdialog->pcity);
4023 }
4024 close_happiness_dialog(pdialog->pcity);
4025
4026 pdialog->pcity = new_pcity;
4027
4028 /* reinitialize happiness, and cma dialogs */
4031 citizens_dialog_display(pdialog->pcity));
4032 }
4034 get_top_happiness_display(pdialog->pcity, low_citydlg, pdialog->shell));
4035 if (!client_is_observer()) {
4036 fc_assert(pdialog->cma_editor != NULL);
4037 pdialog->cma_editor->pcity = new_pcity;
4038 }
4039
4040 reset_city_worklist(pdialog->production.worklist, pdialog->pcity);
4041
4042 can_slide = FALSE;
4043 center_tile_mapcanvas(pdialog->pcity->tile);
4044 can_slide = TRUE;
4045 if (!client_is_observer()) {
4046 set_cityopt_values(pdialog); /* Need not be in real_city_dialog_refresh */
4047 }
4048
4050
4051 /* Recenter the city map(s) */
4053 if (pdialog->happiness.map_canvas.sw) {
4055 }
4056}
4057
4058/***********************************************************************/
4062{
4064 refresh_worklist(pdialog->production.worklist);
4066}
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1271
bool action_ever_possible(action_id action)
Definition actions.c:7505
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:740
#define n
Definition astring.c:77
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
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:666
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:740
const char * city_name_getx(const struct city *pcity)
Definition city.c:1166
int city_granary_size(int city_size)
Definition city.c:2199
int city_build_slots(const struct city *pcity)
Definition city.c:3000
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
int city_superspecialists(const struct city *pcity)
Definition city.c:3426
const char * city_name_get(const struct city *pcity)
Definition city.c:1157
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1308
bool is_city_option_set(const struct city *pcity, enum city_options option)
Definition city.c:3496
int city_population(const struct city *pcity)
Definition city.c:1243
int city_unit_unhappiness(const struct civ_map *nmap, struct unit *punit, int *free_unhappy)
Definition city.c:3117
bool city_unhappy(const struct city *pcity)
Definition city.c:1679
bool city_celebrating(const struct city *pcity)
Definition city.c:1698
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2938
bool city_happy(const struct city *pcity)
Definition city.c:1667
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target, const enum req_problem_type prob_type)
Definition city.c:1028
citizens city_specialists(const struct city *pcity)
Definition city.c:3411
int city_turns_to_grow(const struct city *pcity)
Definition city.c:2049
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:703
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
citizen_category
Definition city.h:265
#define city_owner(_pcity_)
Definition city.h:564
#define MAX_CITY_SIZE
Definition city.h:104
@ FEELING_FINAL
Definition city.h:282
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)
int city_try_fill_superspecialists(struct city *pcity, int cat_len, enum citizen_category *categories)
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)
static struct ai_type * self
Definition classicai.c:47
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:821
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:650
cid cid_encode(struct universal target)
Definition climisc.c:483
int collect_already_built_targets(struct universal *targets, struct city *pcity)
Definition climisc.c:918
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:89
#define cid_production
Definition climisc.h:71
int cid
Definition climisc.h:31
static struct fc_sockaddr_list * list
Definition clinet.c:102
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:77
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:176
#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 const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
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:100
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:842
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:779
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:804
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1090
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1111
#define extra_index(_e_)
Definition extras.h:183
int Impr_type_id
Definition fc_types.h:237
@ RPT_CERTAIN
Definition fc_types.h:516
#define EC_NONE
Definition fc_types.h:808
@ TR_SUCCESS
Definition fc_types.h:941
#define ERM_NONE
Definition fc_types.h:831
@ O_SHIELD
Definition fc_types.h:103
@ O_FOOD
Definition fc_types.h:103
@ O_TRADE
Definition fc_types.h:103
@ O_SCIENCE
Definition fc_types.h:103
@ O_LUXURY
Definition fc_types.h:103
@ O_GOLD
Definition fc_types.h:103
#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:743
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:106
#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:2893
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:2952
static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
Definition citydlg.c:3063
static void city_dialog_update_citizens(struct city_dialog *pdialog)
Definition citydlg.c:1870
static void city_destroy_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3476
static void city_dialog_update_title(struct city_dialog *pdialog)
Definition citydlg.c:1831
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
#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:3400
static bool low_citydlg
Definition citydlg.c:230
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:2085
static void citydlg_response_callback(GtkDialog *dlg, gint response, void *data)
Definition citydlg.c:2519
static void buy_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3191
void real_city_dialog_refresh(struct city *pcity)
Definition citydlg.c:487
static void unit_center_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2792
static struct city_dialog * get_city_dialog(struct city *pcity)
Definition citydlg.c:387
@ 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
#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:1944
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:3055
static void city_dialog_update_present_units(struct city_dialog *pdialog)
Definition citydlg.c:2373
#define CITYMAP_SCALE
Definition citydlg.c:76
static gboolean citizens_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2973
static void change_production_callback(GtkComboBox *combo, struct city_dialog *pdialog)
Definition citydlg.c:3254
static void unit_load_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2867
static void set_cityopt_values(struct city_dialog *pdialog)
Definition citydlg.c:3442
static void close_city_dialog(struct city_dialog *pdialog)
Definition citydlg.c:3537
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:3204
#define dialog_list_iterate_end
Definition citydlg.c:93
static void impr_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition citydlg.c:3327
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:3408
static void city_dialog_map_recenter(GtkWidget *map_canvas_sw)
Definition citydlg.c:462
@ 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
static void draw_map_canvas(struct city_dialog *pdialog)
Definition citydlg.c:3179
static struct @145 workertask_req
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:3273
#define dialog_list_iterate(dialoglist, pdialog)
Definition citydlg.c:91
static void supported_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2819
static void city_dialog_update_prev_next(void)
Definition citydlg.c:2480
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:3468
static struct dialog_list * dialog_list
Definition citydlg.c:216
static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3312
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:2939
static void unit_fortify_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2906
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:2615
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:2919
#define unit_node_vector_iterate(list, elt)
Definition citydlg.c:106
static void rename_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3366
static void switch_city_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3546
#define CITYMAP_WIDTH
Definition citydlg.c:74
static void city_dialog_update_map(struct city_dialog *pdialog)
Definition citydlg.c:2063
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:2880
static void show_units_response(void *data)
Definition citydlg.c:2532
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:2266
static void unit_activate_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2805
static void present_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2844
static void set_city_workertask(GtkWidget *w, gpointer data)
Definition citydlg.c:3000
static void rename_popup_callback(gpointer data, gint response, const char *input)
Definition citydlg.c:3383
static void city_dialog_update_improvement_list(struct city_dialog *pdialog)
Definition citydlg.c:2209
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:2553
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:126
GtkWidget * map_canvas
Definition gui_main.c:108
int screen_height(void)
Definition gui_main.c:2562
#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:196
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
const char * tooltip
Definition repodlgs.c:1315
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:3792
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:3303
static gboolean middle_present_unit_release(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:2799
static bool create_unit_menu(struct city_dialog *pdialog, struct unit *punit, GtkWidget *wdg, bool supported)
Definition citydlg.c:2600
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:2845
static gboolean left_button_down_citymap(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:3274
@ COUNTERS_PAGE
Definition citydlg.c:115
static void close_citydlg_unit_popover(struct city_dialog *pdialog)
Definition citydlg.c:2864
static gboolean middle_supported_unit_release(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition citydlg.c:2823
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:519
void put_unit_picture(struct unit *punit, GtkPicture *p, int height)
Definition mapview.c:494
void picture_set_from_surface(GtkPicture *pic, cairo_surface_t *surf)
Definition sprite.c:544
static FcProdRow * fc_prod_row_new(void)
Definition citydlg.c:481
static void prod_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition citydlg.c:1213
static void fc_impr_row_finalize(GObject *gobject)
Definition citydlg.c:399
#define FC_TYPE_IMPR_ROW
Definition citydlg.c:345
#define IMPR_ROW_UPKEEP
Definition citydlg.c:370
#define FC_TYPE_PROD_ROW
Definition citydlg.c:372
#define PROD_ROW_NAME
Definition citydlg.c:394
static void fc_impr_row_class_init(FcImprRowClass *klass)
Definition citydlg.c:415
#define IMPR_ROW_DESC
Definition citydlg.c:369
static FcImprRow * fc_impr_row_new(void)
Definition citydlg.c:434
static void fc_impr_row_init(FcImprRow *self)
Definition citydlg.c:426
static void impr_factory_setup(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition citydlg.c:1084
#define IMPR_ROW_PIXBUF
Definition citydlg.c:368
static void fc_prod_row_finalize(GObject *gobject)
Definition citydlg.c:446
#define PROD_ROW_PIXBUF
Definition citydlg.c:393
static void fc_prod_row_init(FcProdRow *self)
Definition citydlg.c:473
static void prod_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition citydlg.c:1178
static gboolean query_impr_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, gpointer data)
Definition citydlg.c:1102
static void impr_factory_bind(GtkSignalListItemFactory *self, GtkListItem *list_item, gpointer user_data)
Definition citydlg.c:1041
static void fc_prod_row_class_init(FcProdRowClass *klass)
Definition citydlg.c:462
void alert_close_response(GObject *dialog, GAsyncResult *result, gpointer data)
Definition gui_stuff.c:1176
int get_column_view_row(GtkWidget *cview, int y)
Definition gui_stuff.c:1185
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:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
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)
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:350
bool unit_can_load(const struct unit *punit)
Definition movement.c:934
static const char * name_translation_get(const struct name_translation *ptrans)
#define GUI_GTK5_CITYDLG_MAX_XSIZE
Definition options.h:742
#define GUI_GTK5_CITYDLG_MAX_YSIZE
Definition options.h:746
#define GUI_GTK5_CITYDLG_MIN_XSIZE
Definition options.h:741
#define GUI_GTK5_CITYDLG_MIN_YSIZE
Definition options.h:745
int len
Definition packhand.c:129
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1217
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1191
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
GObjectClass parent_class
Definition citydlg.c:363
int upkeep
Definition citydlg.c:356
const struct impr_type * impr
Definition citydlg.c:353
GdkPixbuf * sprite
Definition citydlg.c:354
const char * tooltip
Definition citydlg.c:358
char * description
Definition citydlg.c:355
bool redundant
Definition citydlg.c:357
GObject parent_instance
Definition citydlg.c:351
GObjectClass parent_class
Definition citydlg.c:388
bool useless
Definition citydlg.c:383
GObject parent_instance
Definition citydlg.c:378
const char * name
Definition citydlg.c:380
GdkPixbuf * sprite
Definition citydlg.c:382
cairo_surface_t * surface
Definition canvas.h:23
GtkWidget * prev_command
Definition citydlg.c:208
GtkWidget * name_label
Definition citydlg.c:141
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 * 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 * disband_on_settler
Definition citydlg.c:198
struct city_map_canvas map_canvas
Definition citydlg.c:150
enum city_dialog::@217 page
GListStore * improvement_list
Definition citydlg.c:156
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 city_dialog::@148 happiness
struct unit_node_vector present_units
Definition citydlg.c:164
city_map * view
Definition citydlg.h:446
GtkWidget * popover
Definition citydlg.c:147
GtkWidget * citizen_pics
Definition citydlg.c:148
GtkWidget * citizens
Definition citydlg.c:185
GListStore * change_prod_store
Definition citydlg.c:169
GtkWidget * show_units_command
Definition citydlg.c:207
Impr_type_id sell_id
Definition citydlg.c:211
struct city_dialog::@150 misc
struct cma_dialog * cma_editor
Definition citydlg.c:193
cairo_surface_t * citizen_surface
Definition citydlg.c:147
GtkWidget * shell
Definition citydlg.c:140
GtkWidget * worklist
Definition citydlg.c:176
GtkSingleSelection * change_prod_selection
Definition citydlg.c:170
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
GtkWidget * present_unit_table
Definition citydlg.c:161
struct city_dialog::@149 counters
GtkWidget * notebook
Definition citydlg.c:143
struct city_dialog::@146 overview
GtkWidget * next_command
Definition citydlg.c:209
GtkTreeSelection * change_selection
Definition citydlg.c:204
struct city_dialog::@147 production
GtkWidget * darea
Definition citydlg.c:134
GtkWidget * sw
Definition citydlg.c:132
Definition city.h:318
int * counter_values
Definition city.h:406
struct unit_list * info_units_present
Definition city.h:474
struct unit_list * info_units_supported
Definition city.h:473
citizens size
Definition city.h:330
int illness
Definition city.h:434
int buy_cost
Definition city.h:466
struct city::@18::@21 client
struct tile * tile
Definition city.h:320
struct unit_list * units_supported
Definition city.h:404
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:281
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int height
Definition citydlg.c:98
GtkEventController * right
Definition citydlg.c:101
GtkWidget * cmd
Definition citydlg.c:96
GtkWidget * pix
Definition citydlg.c:97
GtkEventController * middle
Definition citydlg.c:100
GtkEventController * left
Definition citydlg.c:99
Definition unit.h:139
int upkeep[O_LAST]
Definition unit.h:149
enum unit_activity activity
Definition unit.h:158
int id
Definition unit.h:146
struct tile * tile
Definition unit.h:141
struct unit::@84::@86 client
int homecity
Definition unit.h:147
struct player * owner
Definition unit.h:144
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
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:925
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char * unit_description(struct unit *punit)
Definition text.c:528
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:7033
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:927
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:815
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:963
int tileset_unit_with_upkeep_height(const struct tileset *t)
Definition tilespec.c:885
struct sprite * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Definition tilespec.c:6972
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7055
const struct unit_type * utype
Definition fc_types.h:536
const struct impr_type * building
Definition fc_types.h:529
bool can_unit_change_homecity_to(const struct civ_map *nmap, const struct unit *punit, const struct city *pcity)
Definition unit.c:508
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2526
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:402
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:793
#define unit_tile(_pu)
Definition unit.h:408
#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:126
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1729
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
void economy_report_dialog_update(void)
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66