Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-3.22/citydlg.c Source File

Freeciv-3.1

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/gdkkeysyms.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 "game.h"
36#include "map.h"
37#include "movement.h"
38#include "packets.h"
39#include "player.h"
40#include "unitlist.h"
41
42/* client */
43#include "chatline_common.h"
44#include "client_main.h"
45#include "colors.h"
46#include "control.h"
47#include "climap.h"
48#include "options.h"
49#include "text.h"
50#include "tilespec.h"
51
52/* client/agents */
53#include "cma_fec.h"
54
55/* client/gui-gtk-3.22 */
56#include "choice_dialog.h"
57#include "citizensinfo.h"
58#include "cityrep.h"
59#include "cma_fe.h"
60#include "dialogs.h"
61#include "graphics.h"
62#include "gui_main.h"
63#include "gui_stuff.h"
64#include "happiness.h"
65#include "helpdlg.h"
66#include "inputdlg.h"
67#include "mapview.h"
68#include "repodlgs.h"
69#include "wldlg.h"
70
71#include "citydlg.h"
72
73#define CITYMAP_WIDTH MIN(512, canvas_width)
74#define CITYMAP_HEIGHT (CITYMAP_WIDTH * canvas_height / canvas_width)
75#define CITYMAP_SCALE ((double)CITYMAP_WIDTH / (double)canvas_width)
76
77#define TINYSCREEN_MAX_HEIGHT (500 - 1)
78
79/* Only CDLGR_UNITS button currently uses these, others have
80 * direct callback. */
81 enum citydlg_response { CDLGR_UNITS, CDLGR_PREV, CDLGR_NEXT };
82
83struct city_dialog;
84
85/* get 'struct dialog_list' and related function */
86#define SPECLIST_TAG dialog
87#define SPECLIST_TYPE struct city_dialog
88#include "speclist.h"
89
90#define dialog_list_iterate(dialoglist, pdialog) \
91 TYPED_LIST_ITERATE(struct city_dialog, dialoglist, pdialog)
92#define dialog_list_iterate_end LIST_ITERATE_END
93
94struct unit_node {
95 GtkWidget *cmd;
96 GtkWidget *pix;
97 int height;
98};
99
100/* get 'struct unit_node' and related function */
101#define SPECVEC_TAG unit_node
102#define SPECVEC_TYPE struct unit_node
103#include "specvec.h"
104
105#define unit_node_vector_iterate(list, elt) \
106 TYPED_VECTOR_ITERATE(struct unit_node, list, elt)
107#define unit_node_vector_iterate_end VECTOR_ITERATE_END
108
109#define NUM_CITIZENS_SHOWN 30
110
111 enum { OVERVIEW_PAGE, WORKLIST_PAGE, HAPPINESS_PAGE, CMA_PAGE,
112 SETTINGS_PAGE, STICKY_PAGE,
113 NUM_PAGES /* the number of pages in city dialog notebook
114 * must match the entries in misc_whichtab_label[] */
115};
116
117enum {
118 INFO_SIZE, INFO_FOOD, INFO_SHIELD, INFO_TRADE, INFO_GOLD,
119 INFO_LUXURY, INFO_SCIENCE, INFO_GRANARY, INFO_GROWTH,
120 INFO_CORRUPTION, INFO_WASTE, INFO_CULTURE, INFO_POLLUTION,
121 INFO_ILLNESS, INFO_STEAL, INFO_AIRLIFT,
122 NUM_INFO_FIELDS /* number of fields in city_info panel
123 * must match entries in output_label[] */
124};
125
126/* minimal size for the city map scrolling windows*/
127#define CITY_MAP_MIN_SIZE_X 200
128#define CITY_MAP_MIN_SIZE_Y 150
129
130struct city_map_canvas {
131 GtkWidget *sw;
132 GtkWidget *ebox;
133 GtkWidget *darea;
134};
135
136struct city_dialog {
137 struct city *pcity;
138
139 GtkWidget *shell;
140 GtkWidget *name_label;
141 cairo_surface_t *map_canvas_store_unscaled;
142 GtkWidget *notebook;
143
144 GtkWidget *popup_menu;
145 GtkWidget *citizen_images;
146 cairo_surface_t *citizen_surface;
147
148 struct {
149 struct city_map_canvas map_canvas;
150
151 GtkWidget *production_bar;
152 GtkWidget *production_combo;
153 GtkWidget *buy_command;
154 GtkWidget *improvement_list;
155
156 GtkWidget *supported_units_frame;
157 GtkWidget *supported_unit_table;
158
159 GtkWidget *present_units_frame;
160 GtkWidget *present_unit_table;
161
162 struct unit_node_vector supported_units;
163 struct unit_node_vector present_units;
164
165 GtkWidget *info_ebox[NUM_INFO_FIELDS];
166 GtkWidget *info_label[NUM_INFO_FIELDS];
167
168 GtkListStore* change_production_store;
169 } overview;
170
171 struct {
172 GtkWidget *production_label;
173 GtkWidget *production_bar;
174 GtkWidget *buy_command;
175 GtkWidget *worklist;
176 } production;
177
178 struct {
179 struct city_map_canvas map_canvas;
180
181 GtkWidget *widget;
182 GtkWidget *info_ebox[NUM_INFO_FIELDS];
183 GtkWidget *info_label[NUM_INFO_FIELDS];
184 GtkWidget *citizens;
185 } happiness;
186
187 struct cma_dialog *cma_editor;
188
189 struct {
190 GtkWidget *rename_command;
191 GtkWidget *new_citizens_radio[3];
192 GtkWidget *disband_on_settler;
193 GtkWidget *whichtab_radio[NUM_PAGES];
194 short block_signal;
195 } misc;
196
197 GtkWidget *sell_shell;
198 GtkTreeSelection *change_selection;
199 GtkWidget *rename_shell;
200
201 GtkWidget *show_units_command;
202 GtkWidget *prev_command;
203 GtkWidget *next_command;
204
205 Impr_type_id sell_id;
206
207 int cwidth;
208};
209
210 static struct dialog_list *dialog_list;
211 static bool city_dialogs_have_been_initialised = FALSE;
212 static int canvas_width, canvas_height;
213 static int new_dialog_def_page = OVERVIEW_PAGE;
214 static int last_page = OVERVIEW_PAGE;
215
216 static bool is_showing_workertask_dialog = FALSE;
217
218static struct
219{
220 struct city *owner;
221 struct tile *loc;
222} workertask_req;
223
224 static bool low_citydlg;
225
226/****************************************/
227
228static void initialize_city_dialogs(void);
229static void city_dialog_map_create(struct city_dialog *pdialog,
230 struct city_map_canvas *cmap_canvas);
231static void city_dialog_map_recenter(GtkWidget *map_canvas_sw);
232
233static struct city_dialog *get_city_dialog(struct city *pcity);
234static gboolean keyboard_handler(GtkWidget * widget, GdkEventKey * event,
235 struct city_dialog *pdialog);
236
237static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
238 GtkWidget **info_ebox,
239 GtkWidget **info_label);
240static void create_and_append_overview_page(struct city_dialog *pdialog);
241static void create_and_append_map_page(struct city_dialog *pdialog);
242static void create_and_append_buildings_page(struct city_dialog *pdialog);
243static void create_and_append_worklist_page(struct city_dialog *pdialog);
244static void create_and_append_happiness_page(struct city_dialog *pdialog);
245static void create_and_append_cma_page(struct city_dialog *pdialog);
246static void create_and_append_settings_page(struct city_dialog *pdialog);
247
248static struct city_dialog *create_city_dialog(struct city *pcity);
249
250static void city_dialog_update_title(struct city_dialog *pdialog);
251static void city_dialog_update_citizens(struct city_dialog *pdialog);
252static void city_dialog_update_information(GtkWidget **info_ebox,
253 GtkWidget **info_label,
254 struct city_dialog *pdialog);
255static void city_dialog_update_map(struct city_dialog *pdialog);
256static void city_dialog_update_building(struct city_dialog *pdialog);
257static void city_dialog_update_improvement_list(struct city_dialog
258 *pdialog);
259static void city_dialog_update_supported_units(struct city_dialog
260 *pdialog);
261static void city_dialog_update_present_units(struct city_dialog *pdialog);
262static void city_dialog_update_prev_next(void);
263
264static void show_units_response(void *data);
265
266static gboolean supported_unit_callback(GtkWidget * w, GdkEventButton * ev,
267 gpointer data);
268static gboolean present_unit_callback(GtkWidget * w, GdkEventButton * ev,
269 gpointer data);
270static gboolean supported_unit_middle_callback(GtkWidget * w,
271 GdkEventButton * ev,
272 gpointer data);
273static gboolean present_unit_middle_callback(GtkWidget * w,
274 GdkEventButton * ev,
275 gpointer data);
276
277static void unit_center_callback(GtkWidget * w, gpointer data);
278static void unit_activate_callback(GtkWidget * w, gpointer data);
279static void supported_unit_activate_close_callback(GtkWidget * w,
280 gpointer data);
281static void present_unit_activate_close_callback(GtkWidget * w,
282 gpointer data);
283static void unit_load_callback(GtkWidget * w, gpointer data);
284static void unit_unload_callback(GtkWidget * w, gpointer data);
285static void unit_sentry_callback(GtkWidget * w, gpointer data);
286static void unit_fortify_callback(GtkWidget * w, gpointer data);
287static void unit_disband_callback(GtkWidget * w, gpointer data);
288static void unit_homecity_callback(GtkWidget * w, gpointer data);
289static void unit_upgrade_callback(GtkWidget * w, gpointer data);
290
291static gboolean citizens_callback(GtkWidget * w, GdkEventButton * ev,
292 gpointer data);
293static gboolean button_down_citymap(GtkWidget * w, GdkEventButton * ev,
294 gpointer data);
295static void draw_map_canvas(struct city_dialog *pdialog);
296
297static void buy_callback(GtkWidget * w, gpointer data);
298static void change_production_callback(GtkComboBox *combo,
299 struct city_dialog *pdialog);
300
301static void sell_callback(struct impr_type *pimprove, gpointer data);
302static void sell_callback_response(GtkWidget *w, gint response, gpointer data);
303
304static void impr_callback(GtkTreeView *view, GtkTreePath *path,
305 GtkTreeViewColumn *col, gpointer data);
306
307static void rename_callback(GtkWidget * w, gpointer data);
308static void rename_popup_callback(gpointer data, gint response,
309 const char *input);
310static void set_cityopt_values(struct city_dialog *pdialog);
311static void cityopt_callback(GtkWidget * w, gpointer data);
312static void misc_whichtab_callback(GtkWidget * w, gpointer data);
313
314static void city_destroy_callback(GtkWidget *w, gpointer data);
315static void close_city_dialog(struct city_dialog *pdialog);
316static void citydlg_response_callback(GtkDialog *dlg, gint response,
317 void *data);
318static void close_callback(GtkWidget *w, gpointer data);
319static void switch_city_callback(GtkWidget *w, gpointer data);
320
321/**********************************************************************/
325 static void init_citydlg_dimensions(void)
326{
327 canvas_width = get_citydlg_canvas_width();
328 canvas_height = get_citydlg_canvas_height();
329}
330
331/**********************************************************************/
334 static void initialize_city_dialogs(void)
335{
336 int height;
337
338 fc_assert_ret(!city_dialogs_have_been_initialised);
339
340 dialog_list = dialog_list_new();
341 init_citydlg_dimensions();
342 height = screen_height();
343
344 /* Use default layout when height cannot be determined
345 * (when height == 0) */
346 if (height > 0 && height <= TINYSCREEN_MAX_HEIGHT) {
347 low_citydlg = TRUE;
348 } else {
349 low_citydlg = FALSE;
350 }
351
352 city_dialogs_have_been_initialised = TRUE;
353}
354
355/**********************************************************************/
358 void reset_city_dialogs(void)
359{
360 if (!city_dialogs_have_been_initialised) {
361 return;
362 }
363
364 init_citydlg_dimensions();
365
366 dialog_list_iterate(dialog_list, pdialog) {
367 /* There's no reasonable way to resize a GtkImage, so we don't try.
368 Instead we just redraw the overview within the existing area. The
369 player has to close and reopen the dialog to fix this. */
370 city_dialog_update_map(pdialog);
371 } dialog_list_iterate_end;
372
373 popdown_all_city_dialogs();
374}
375
376/**********************************************************************/
380 static struct city_dialog *get_city_dialog(struct city *pcity)
381{
382 if (!city_dialogs_have_been_initialised) {
383 initialize_city_dialogs();
384 }
385
386 dialog_list_iterate(dialog_list, pdialog) {
387 if (pdialog->pcity == pcity)
388 return pdialog;
389 }
390 dialog_list_iterate_end;
391 return NULL;
392}
393
394/**********************************************************************/
397 static gboolean canvas_exposed_cb(GtkWidget *w, cairo_t *cr,
398 gpointer data)
399{
400 struct city_dialog *pdialog = data;
401
402 cairo_scale(cr, CITYMAP_SCALE, CITYMAP_SCALE);
403 cairo_set_source_surface(cr, pdialog->map_canvas_store_unscaled, 0, 0);
404 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
405 cairo_paint_with_alpha(cr, 0.5);
406 } else {
407 cairo_paint(cr);
408 }
409
410 return TRUE;
411}
412
413/**********************************************************************/
416 static void city_dialog_map_create(struct city_dialog *pdialog,
417 struct city_map_canvas *cmap_canvas)
418{
419 GtkWidget *sw, *ebox, *darea;
420
421 sw = gtk_scrolled_window_new(NULL, NULL);
422 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(sw),
423 CITYMAP_WIDTH);
424 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(sw),
425 CITYMAP_HEIGHT);
426 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
427 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
428 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
429 GTK_SHADOW_NONE);
430
431 ebox = gtk_event_box_new();
432 gtk_widget_set_halign(ebox, GTK_ALIGN_CENTER);
433 gtk_widget_set_valign(ebox, GTK_ALIGN_CENTER);
434 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
435 gtk_container_add(GTK_CONTAINER(sw), ebox);
436
437 darea = gtk_drawing_area_new();
438 gtk_widget_add_events(darea, GDK_BUTTON_PRESS_MASK);
439 gtk_widget_set_size_request(darea, CITYMAP_WIDTH, CITYMAP_HEIGHT);
440 g_signal_connect(ebox, "button-press-event",
441 G_CALLBACK(button_down_citymap), pdialog);
442 g_signal_connect(darea, "draw",
443 G_CALLBACK(canvas_exposed_cb), pdialog);
444 gtk_container_add(GTK_CONTAINER(ebox), darea);
445
446 /* save all widgets for the city map */
447 cmap_canvas->sw = sw;
448 cmap_canvas->ebox = ebox;
449 cmap_canvas->darea = darea;
450}
451
452/**********************************************************************/
455 static void city_dialog_map_recenter(GtkWidget *map_canvas_sw)
456{
457 GtkAdjustment *adjust = NULL;
458 gdouble value;
459
460 fc_assert_ret(map_canvas_sw != NULL);
461
462 adjust = gtk_scrolled_window_get_hadjustment(
463 GTK_SCROLLED_WINDOW(map_canvas_sw));
464 value = (gtk_adjustment_get_lower(adjust)
465 + gtk_adjustment_get_upper(adjust)
466 - gtk_adjustment_get_page_size(adjust)) / 2;
467 gtk_adjustment_set_value(adjust, value);
468
469 adjust = gtk_scrolled_window_get_vadjustment(
470 GTK_SCROLLED_WINDOW(map_canvas_sw));
471 value = (gtk_adjustment_get_lower(adjust)
472 + gtk_adjustment_get_upper(adjust)
473 - gtk_adjustment_get_page_size(adjust)) / 2;
474 gtk_adjustment_set_value(adjust, value);
475}
476
477/**********************************************************************/
480 void real_city_dialog_refresh(struct city *pcity)
481{
482 struct city_dialog *pdialog = get_city_dialog(pcity);
483
484 log_debug("CITYMAP_WIDTH: %d", CITYMAP_WIDTH);
485 log_debug("CITYMAP_HEIGHT: %d", CITYMAP_HEIGHT);
486 log_debug("CITYMAP_SCALE: %.3f", CITYMAP_SCALE);
487
488 if (city_owner(pcity) == client.conn.playing) {
489 city_report_dialog_update_city(pcity);
490 economy_report_dialog_update();
491 }
492
493 if (!pdialog) {
494 return;
495 }
496
497 city_dialog_update_title(pdialog);
498 city_dialog_update_citizens(pdialog);
499 city_dialog_update_information(pdialog->overview.info_ebox,
500 pdialog->overview.info_label, pdialog);
501 city_dialog_update_map(pdialog);
502 city_dialog_update_building(pdialog);
503 city_dialog_update_improvement_list(pdialog);
504 city_dialog_update_supported_units(pdialog);
505 city_dialog_update_present_units(pdialog);
506
507 if (!client_has_player() || city_owner(pcity) == client_player()) {
508 bool have_present_units = (unit_list_size(pcity->tile->units) > 0);
509
510 refresh_worklist(pdialog->production.worklist);
511
512 if (!low_citydlg) {
513 city_dialog_update_information(pdialog->happiness.info_ebox,
514 pdialog->happiness.info_label, pdialog);
515 }
516 refresh_happiness_dialog(pdialog->pcity);
517 if (game.info.citizen_nationality) {
518 citizens_dialog_refresh(pdialog->pcity);
519 }
520
521 if (!client_is_observer()) {
522 refresh_cma_dialog(pdialog->pcity, REFRESH_ALL);
523 }
524
525 gtk_widget_set_sensitive(pdialog->show_units_command,
526 can_client_issue_orders()
527 && have_present_units);
528 } else {
529 /* Set the buttons we do not want live while a Diplomat investigates */
530 gtk_widget_set_sensitive(pdialog->show_units_command, FALSE);
531 }
532}
533
534/**********************************************************************/
538 void refresh_unit_city_dialogs(struct unit *punit)
539{
540 struct city *pcity_sup, *pcity_pre;
541 struct city_dialog *pdialog;
542
543 pcity_sup = game_city_by_number(punit->homecity);
544 pcity_pre = tile_city(unit_tile(punit));
545
546 if (pcity_sup && (pdialog = get_city_dialog(pcity_sup))) {
547 city_dialog_update_supported_units(pdialog);
548 }
549
550 if (pcity_pre && (pdialog = get_city_dialog(pcity_pre))) {
551 city_dialog_update_present_units(pdialog);
552 }
553}
554
555/**********************************************************************/
558 void real_city_dialog_popup(struct city *pcity)
559{
560 struct city_dialog *pdialog;
561
562 if (!(pdialog = get_city_dialog(pcity))) {
563 pdialog = create_city_dialog(pcity);
564 }
565
566 gtk_window_present(GTK_WINDOW(pdialog->shell));
567
568 /* center the city map(s); this must be *after* the city dialog was drawn
569 * else the size information is missing! */
570 city_dialog_map_recenter(pdialog->overview.map_canvas.sw);
571 if (pdialog->happiness.map_canvas.sw) {
572 city_dialog_map_recenter(pdialog->happiness.map_canvas.sw);
573 }
574}
575
576/**********************************************************************/
579 bool city_dialog_is_open(struct city *pcity)
580{
581 return get_city_dialog(pcity) != NULL;
582}
583
584/**********************************************************************/
587 void popdown_city_dialog(struct city *pcity)
588{
589 struct city_dialog *pdialog = get_city_dialog(pcity);
590
591 if (pdialog) {
592 close_city_dialog(pdialog);
593 }
594}
595
596/**********************************************************************/
599 void popdown_all_city_dialogs(void)
600{
601 if (!city_dialogs_have_been_initialised) {
602 return;
603 }
604
605 while (dialog_list_size(dialog_list)) {
606 close_city_dialog(dialog_list_get(dialog_list, 0));
607 }
608 dialog_list_destroy(dialog_list);
609
610 city_dialogs_have_been_initialised = FALSE;
611}
612
613/**********************************************************************/
616 static gboolean keyboard_handler(GtkWidget * widget, GdkEventKey * event,
617 struct city_dialog *pdialog)
618{
619 if (event->state & GDK_CONTROL_MASK) {
620 switch (event->keyval) {
621 case GDK_KEY_Left:
622 gtk_notebook_prev_page(GTK_NOTEBOOK(pdialog->notebook));
623 return TRUE;
624
625 case GDK_KEY_Right:
626 gtk_notebook_next_page(GTK_NOTEBOOK(pdialog->notebook));
627 return TRUE;
628
629 default:
630 break;
631 }
632 }
633
634 return FALSE;
635}
636
637/**********************************************************************/
640 static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev,
641 gpointer data)
642{
643 gtk_grab_remove(w);
644 gdk_seat_ungrab(gdk_device_get_seat(ev->device));
645 gtk_widget_destroy(w);
646
647 return FALSE;
648}
649
650/**********************************************************************/
653 static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev,
654 gpointer data)
655{
656 struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
657
658 if (ev->button == 1) {
659 GtkWidget *p, *label, *frame;
660 char buf[1024];
661
662 switch (GPOINTER_TO_UINT(data)) {
663 case INFO_SIZE:
664 fc_snprintf(buf, sizeof(buf), _("Population: %d, Specialists: %d"),
665 pdialog->pcity->size, city_specialists(pdialog->pcity));
666 break;
667 case INFO_FOOD:
668 get_city_dialog_output_text(pdialog->pcity, O_FOOD, buf, sizeof(buf));
669 break;
670 case INFO_SHIELD:
671 get_city_dialog_output_text(pdialog->pcity, O_SHIELD,
672 buf, sizeof(buf));
673 break;
674 case INFO_TRADE:
675 get_city_dialog_output_text(pdialog->pcity, O_TRADE, buf, sizeof(buf));
676 break;
677 case INFO_GOLD:
678 get_city_dialog_output_text(pdialog->pcity, O_GOLD, buf, sizeof(buf));
679 break;
680 case INFO_SCIENCE:
681 get_city_dialog_output_text(pdialog->pcity, O_SCIENCE,
682 buf, sizeof(buf));
683 break;
684 case INFO_LUXURY:
685 get_city_dialog_output_text(pdialog->pcity, O_LUXURY,
686 buf, sizeof(buf));
687 break;
688 case INFO_CULTURE:
689 get_city_dialog_culture_text(pdialog->pcity, buf, sizeof(buf));
690 break;
691 case INFO_POLLUTION:
692 get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
693 break;
694 case INFO_ILLNESS:
695 get_city_dialog_illness_text(pdialog->pcity, buf, sizeof(buf));
696 break;
697 case INFO_AIRLIFT:
698 get_city_dialog_airlift_text(pdialog->pcity, buf, sizeof(buf));
699 break;
700 default:
701 return TRUE;
702 }
703
704 p = gtk_window_new(GTK_WINDOW_POPUP);
705 gtk_widget_set_name(p, "Freeciv");
706 gtk_container_set_border_width(GTK_CONTAINER(p), 2);
707 gtk_window_set_transient_for(GTK_WINDOW(p), GTK_WINDOW(pdialog->shell));
708 gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
709
710 frame = gtk_frame_new(NULL);
711 gtk_container_add(GTK_CONTAINER(p), frame);
712
713 label = gtk_label_new(buf);
714 gtk_widget_set_name(label, "city_label");
715 gtk_widget_set_margin_start(label, 4);
716 gtk_widget_set_margin_end(label, 4);
717 gtk_widget_set_margin_top(label, 4);
718 gtk_widget_set_margin_bottom(label, 4);
719 gtk_container_add(GTK_CONTAINER(frame), label);
720 gtk_widget_show_all(p);
721
722 gdk_seat_grab(gdk_device_get_seat(ev->device), gtk_widget_get_window(p),
723 GDK_SEAT_CAPABILITY_ALL_POINTING,
724 TRUE, NULL, (GdkEvent *)ev, NULL, NULL);
725 gtk_grab_add(p);
726
727 g_signal_connect_after(p, "button_release_event",
728 G_CALLBACK(show_info_button_release), NULL);
729 }
730 return TRUE;
731}
732
733/**********************************************************************/
737 static GtkWidget *create_city_info_table(struct city_dialog *pdialog,
738 GtkWidget **info_ebox,
739 GtkWidget **info_label)
740{
741 int i;
742 GtkWidget *table, *label, *ebox;
743
744 static const char *output_label[NUM_INFO_FIELDS] = {
745 N_("Size:"),
746 N_("Food:"),
747 N_("Prod:"),
748 N_("Trade:"),
749 N_("Gold:"),
750 N_("Luxury:"),
751 N_("Science:"),
752 N_("Granary:"),
753 N_("Change in:"),
754 N_("Corruption:"),
755 N_("Waste:"),
756 N_("Culture:"),
757 N_("Pollution:"),
758 N_("Plague risk:"),
759 N_("Tech Stolen:"),
760 N_("Airlift:"),
761 };
762 static bool output_label_done;
763
764 table = gtk_grid_new();
765 g_object_set(table, "margin", 4, NULL);
766
767 intl_slist(ARRAY_SIZE(output_label), output_label, &output_label_done);
768
769 for (i = 0; i < NUM_INFO_FIELDS; i++) {
770 label = gtk_label_new(output_label[i]);
771 switch (i) {
772 case INFO_SIZE:
773 case INFO_TRADE:
774 case INFO_SCIENCE:
775 case INFO_GROWTH:
776 gtk_widget_set_margin_bottom(label, 5);
777 break;
778
779 case INFO_FOOD:
780 case INFO_GOLD:
781 case INFO_GRANARY:
782 case INFO_CORRUPTION:
783 gtk_widget_set_margin_top(label, 5);
784 break;
785 default:
786 break;
787 }
788 gtk_widget_set_margin_end(label, 5);
789 gtk_widget_set_name(label, "city_label"); /* for font style? */
790 gtk_widget_set_halign(label, GTK_ALIGN_START);
791 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
792 gtk_grid_attach(GTK_GRID(table), label, 0, i, 1, 1);
793
794 ebox = gtk_event_box_new();
795 switch (i) {
796 case INFO_TRADE:
797 case INFO_SCIENCE:
798 case INFO_GROWTH:
799 gtk_widget_set_margin_bottom(ebox, 5);
800 break;
801
802 case INFO_GOLD:
803 case INFO_GRANARY:
804 case INFO_CORRUPTION:
805 gtk_widget_set_margin_top(ebox, 5);
806 break;
807 default:
808 break;
809 }
810 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
811 g_object_set_data(G_OBJECT(ebox), "pdialog", pdialog);
812 g_signal_connect(ebox, "button_press_event",
813 G_CALLBACK(show_info_popup), GUINT_TO_POINTER(i));
814 info_ebox[i] = ebox;
815
816 label = gtk_label_new("");
817 info_label[i] = label;
818 gtk_widget_set_name(label, "city_label"); /* ditto */
819 gtk_widget_set_halign(label, GTK_ALIGN_START);
820 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
821
822 gtk_container_add(GTK_CONTAINER(ebox), label);
823
824 gtk_grid_attach(GTK_GRID(table), ebox, 1, i, 1, 1);
825 }
826
827 /*
828 * Allow special highlighting of emergencies for granary etc by
829 * city_dialog_update_information().
830 */
831 {
832 /* This will persist, and can be shared between overview and happiness
833 * pages. */
834 static GtkCssProvider *emergency_provider = NULL;
835
836 if (emergency_provider == NULL) {
837 emergency_provider = gtk_css_provider_new();
838
839 gtk_css_provider_load_from_data(emergency_provider,
840 ".emergency {\n"
841 " color: rgba(255, 0.0, 0.0, 255);\n"
842 "}",
843 -1, NULL);
844 }
845
846 /* GRANARY */
847 gtk_style_context_add_provider(gtk_widget_get_style_context(info_label[INFO_GRANARY]),
848 GTK_STYLE_PROVIDER(emergency_provider),
849 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
850 /* GROWTH */
851 gtk_style_context_add_provider(gtk_widget_get_style_context(info_label[INFO_GROWTH]),
852 GTK_STYLE_PROVIDER(emergency_provider),
853 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
854 /* POLLUTION */
855 gtk_style_context_add_provider(gtk_widget_get_style_context(info_label[INFO_POLLUTION]),
856 GTK_STYLE_PROVIDER(emergency_provider),
857 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
858 /* ILLNESS */
859 gtk_style_context_add_provider(gtk_widget_get_style_context(info_label[INFO_ILLNESS]),
860 GTK_STYLE_PROVIDER(emergency_provider),
861 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
862 }
863
864 gtk_widget_show_all(table);
865
866 return table;
867}
868
869/**********************************************************************/
872 static void create_citydlg_main_map(struct city_dialog *pdialog,
873 GtkWidget *container)
874{
875 GtkWidget *frame;
876
877 frame = gtk_frame_new(_("City map"));
878 gtk_widget_set_size_request(frame, CITY_MAP_MIN_SIZE_X,
879 CITY_MAP_MIN_SIZE_Y);
880 gtk_container_add(GTK_CONTAINER(container), frame);
881
882 city_dialog_map_create(pdialog, &pdialog->overview.map_canvas);
883 gtk_container_add(GTK_CONTAINER(frame), pdialog->overview.map_canvas.sw);
884}
885
886/**********************************************************************/
889 static GtkWidget *create_citydlg_improvement_list(struct city_dialog *pdialog,
890 GtkWidget *vbox)
891{
892 GtkWidget *view;
893 GtkListStore *store;
894 GtkCellRenderer *rend;
895
896 /* improvements */
897 /* gtk list store columns: 0 - sell value, 1 - sprite,
898 2 - description, 3 - upkeep, 4 - is redundant, 5 - tooltip */
899 store = gtk_list_store_new(6, G_TYPE_POINTER, GDK_TYPE_PIXBUF,
900 G_TYPE_STRING, G_TYPE_INT, G_TYPE_BOOLEAN,
901 G_TYPE_STRING);
902
903 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
904 gtk_widget_set_hexpand(view, TRUE);
905 gtk_widget_set_vexpand(view, TRUE);
906 g_object_unref(store);
907 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
908 gtk_widget_set_name(view, "small_font");
909 pdialog->overview.improvement_list = view;
910
911 rend = gtk_cell_renderer_pixbuf_new();
912 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, NULL,
913 rend, "pixbuf", 1, NULL);
914 rend = gtk_cell_renderer_text_new();
915 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, NULL,
916 rend, "text", 2,
917 "strikethrough", 4, NULL);
918 rend = gtk_cell_renderer_text_new();
919 g_object_set(rend, "xalign", 1.0, NULL);
920 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, NULL,
921 rend, "text", 3,
922 "strikethrough", 4, NULL);
923
924 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(view), 5);
925
926 g_signal_connect(view, "row_activated", G_CALLBACK(impr_callback),
927 pdialog);
928
929 return view;
930}
931
932/**********************************************************************/
948 static void create_and_append_overview_page(struct city_dialog *pdialog)
949{
950 GtkWidget *page, *bottom;
951 GtkWidget *hbox, *right, *vbox, *frame, *table;
952 GtkWidget *label, *sw, *view, *bar, *production_combo;
953 GtkCellRenderer *rend;
954 GtkListStore *production_store;
955 /* TRANS: Overview tab in city dialog */
956 const char *tab_title = _("_Overview");
957 int unit_height = tileset_unit_with_upkeep_height(tileset);
958
959 /* main page */
960 page = gtk_grid_new();
961 gtk_orientable_set_orientation(GTK_ORIENTABLE(page),
962 GTK_ORIENTATION_VERTICAL);
963 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
964 label = gtk_label_new_with_mnemonic(tab_title);
965 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
966
967 if (!low_citydlg) {
968 GtkWidget *middle;
969
970 /* middle: city map, improvements */
971 middle = gtk_grid_new();
972 gtk_grid_set_column_spacing(GTK_GRID(middle), 6);
973 gtk_container_add(GTK_CONTAINER(page), middle);
974
975 /* city map */
976 create_citydlg_main_map(pdialog, middle);
977
978 /* improvements */
979 vbox = gtk_grid_new();
980 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
981 GTK_ORIENTATION_VERTICAL);
982 gtk_container_add(GTK_CONTAINER(middle), vbox);
983
984 view = create_citydlg_improvement_list(pdialog, middle);
985
986 label = g_object_new(GTK_TYPE_LABEL, "label", _("Production:"),
987 "xalign", 0.0, "yalign", 0.5, NULL);
988 gtk_container_add(GTK_CONTAINER(vbox), label);
989
990 hbox = gtk_grid_new();
991 gtk_grid_set_column_spacing(GTK_GRID(hbox), 10);
992 gtk_container_add(GTK_CONTAINER(vbox), hbox);
993
994 production_store = gtk_list_store_new(4, GDK_TYPE_PIXBUF, G_TYPE_STRING,
995 G_TYPE_INT, G_TYPE_BOOLEAN);
996 pdialog->overview.change_production_store = production_store;
997
998 production_combo =
999 gtk_combo_box_new_with_model(GTK_TREE_MODEL(production_store));
1000 gtk_widget_set_hexpand(production_combo, TRUE);
1001 pdialog->overview.production_combo = production_combo;
1002 gtk_container_add(GTK_CONTAINER(hbox), production_combo);
1003 g_object_unref(production_store);
1004 g_signal_connect(production_combo, "changed",
1005 G_CALLBACK(change_production_callback), pdialog);
1006
1007 gtk_cell_layout_clear(GTK_CELL_LAYOUT(production_combo));
1008 rend = gtk_cell_renderer_pixbuf_new();
1009 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(production_combo), rend, TRUE);
1010 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(production_combo),
1011 rend, "pixbuf", 0, NULL);
1012 g_object_set(rend, "xalign", 0.0, NULL);
1013
1014 rend = gtk_cell_renderer_text_new();
1015 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(production_combo), rend, TRUE);
1016 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(production_combo),
1017 rend, "text", 1, "strikethrough", 3, NULL);
1018
1019 bar = gtk_progress_bar_new();
1020 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(bar), TRUE);
1021 pdialog->overview.production_bar = bar;
1022 gtk_container_add(GTK_CONTAINER(production_combo), bar);
1023 gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(production_combo), 3);
1024
1025 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1026
1027 pdialog->overview.buy_command
1028 = icon_label_button_new("system-run", _("_Buy"));
1029 gtk_container_add(GTK_CONTAINER(hbox), GTK_WIDGET(pdialog->overview.buy_command));
1030 g_signal_connect(pdialog->overview.buy_command, "clicked",
1031 G_CALLBACK(buy_callback), pdialog);
1032
1033 label = g_object_new(GTK_TYPE_LABEL, "use-underline", TRUE,
1034 "mnemonic-widget", view,
1035 "label", _("I_mprovements:"),
1036 "xalign", 0.0, "yalign", 0.5, NULL);
1037 gtk_container_add(GTK_CONTAINER(vbox), label);
1038
1039 sw = gtk_scrolled_window_new(NULL, NULL);
1040 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1041 GTK_SHADOW_ETCHED_IN);
1042 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1043 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1044 gtk_container_add(GTK_CONTAINER(vbox), sw);
1045
1046 gtk_container_add(GTK_CONTAINER(sw), view);
1047 } else {
1048 pdialog->overview.buy_command = NULL;
1049 pdialog->overview.production_bar = NULL;
1050 pdialog->overview.production_combo = NULL;
1051 pdialog->overview.change_production_store = NULL;
1052 }
1053
1054 /* bottom: info, units */
1055 bottom = gtk_grid_new();
1056 gtk_grid_set_column_spacing(GTK_GRID(bottom), 6);
1057 gtk_container_add(GTK_CONTAINER(page), bottom);
1058
1059 /* info */
1060 frame = gtk_frame_new(_("Info"));
1061 gtk_container_add(GTK_CONTAINER(bottom), frame);
1062
1063 table = create_city_info_table(pdialog,
1064 pdialog->overview.info_ebox,
1065 pdialog->overview.info_label);
1066 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
1067 gtk_widget_set_valign(table, GTK_ALIGN_CENTER);
1068 gtk_container_add(GTK_CONTAINER(frame), table);
1069
1070 /* right: present and supported units (overview page) */
1071 right = gtk_grid_new();
1072 gtk_orientable_set_orientation(GTK_ORIENTABLE(right),
1073 GTK_ORIENTATION_VERTICAL);
1074 gtk_container_add(GTK_CONTAINER(bottom), right);
1075
1076 pdialog->overview.supported_units_frame = gtk_frame_new("");
1077 gtk_container_add(GTK_CONTAINER(right),
1078 pdialog->overview.supported_units_frame);
1079 pdialog->overview.present_units_frame = gtk_frame_new("");
1080 gtk_container_add(GTK_CONTAINER(right),
1081 pdialog->overview.present_units_frame);
1082
1083 /* supported units */
1084 sw = gtk_scrolled_window_new(NULL, NULL);
1085 gtk_widget_set_hexpand(sw, TRUE);
1086 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1087 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1088 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1089 GTK_SHADOW_NONE);
1090 gtk_container_add(GTK_CONTAINER(pdialog->overview.supported_units_frame),
1091 sw);
1092
1093
1094 table = gtk_grid_new();
1095 gtk_grid_set_column_spacing(GTK_GRID(table), 2);
1096 gtk_widget_set_size_request(table, -1, unit_height);
1097 gtk_container_add(GTK_CONTAINER(sw), table);
1098
1099 gtk_container_set_focus_hadjustment(GTK_CONTAINER(table),
1100 gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(sw)));
1101 gtk_container_set_focus_vadjustment(GTK_CONTAINER(table),
1102 gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)));
1103
1104 pdialog->overview.supported_unit_table = table;
1105 unit_node_vector_init(&pdialog->overview.supported_units);
1106
1107 /* present units */
1108 sw = gtk_scrolled_window_new(NULL, NULL);
1109 gtk_widget_set_hexpand(sw, TRUE);
1110 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1111 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1112 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1113 GTK_SHADOW_NONE);
1114 gtk_container_add(GTK_CONTAINER(pdialog->overview.present_units_frame), sw);
1115
1116 table = gtk_grid_new();
1117 gtk_grid_set_column_spacing(GTK_GRID(table), 2);
1118 gtk_widget_set_size_request(table, -1, unit_height);
1119 gtk_container_add(GTK_CONTAINER(sw), table);
1120
1121 gtk_container_set_focus_hadjustment(GTK_CONTAINER(table),
1122 gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(sw)));
1123 gtk_container_set_focus_vadjustment(GTK_CONTAINER(table),
1124 gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)));
1125
1126 pdialog->overview.present_unit_table = table;
1127 unit_node_vector_init(&pdialog->overview.present_units);
1128
1129 /* show page */
1130 gtk_widget_show_all(page);
1131}
1132
1133/**********************************************************************/
1136 static void create_and_append_map_page(struct city_dialog *pdialog)
1137{
1138 if (low_citydlg) {
1139 GtkWidget *page;
1140 GtkWidget *label;
1141 const char *tab_title = _("Citymap");
1142
1143 page = gtk_grid_new();
1144 gtk_orientable_set_orientation(GTK_ORIENTABLE(page),
1145 GTK_ORIENTATION_VERTICAL);
1146 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
1147 label = gtk_label_new_with_mnemonic(tab_title);
1148 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1149
1150 create_citydlg_main_map(pdialog, page);
1151
1152 gtk_widget_show_all(page);
1153 }
1154}
1155
1156/**********************************************************************/
1159 static void target_drag_data_received(GtkWidget *w,
1160 GdkDragContext *context,
1161 gint x, gint y,
1162 GtkSelectionData *data,
1163 guint info, guint time,
1164 gpointer user_data)
1165{
1166 struct city_dialog *pdialog = (struct city_dialog *) user_data;
1167 GtkTreeModel *model;
1168 GtkTreePath *path;
1169
1170 if (NULL != client.conn.playing
1171 && city_owner(pdialog->pcity) != client.conn.playing) {
1172 gtk_drag_finish(context, FALSE, FALSE, time);
1173 }
1174
1175 if (gtk_tree_get_row_drag_data(data, &model, &path)) {
1176 GtkTreeIter it;
1177
1178 if (gtk_tree_model_get_iter(model, &it, path)) {
1179 cid id;
1180 struct universal univ;
1181
1182 gtk_tree_model_get(model, &it, 0, &id, -1);
1183 univ = cid_production(id);
1184 city_change_production(pdialog->pcity, &univ);
1185 gtk_drag_finish(context, TRUE, FALSE, time);
1186 }
1187 gtk_tree_path_free(path);
1188 }
1189
1190 gtk_drag_finish(context, FALSE, FALSE, time);
1191}
1192
1193/**********************************************************************/
1197 static void create_production_header(struct city_dialog *pdialog, GtkContainer *contain)
1198{
1199 GtkWidget *hbox, *bar;
1200
1201 hbox = gtk_grid_new();
1202 g_object_set(hbox, "margin", 2, NULL);
1203 gtk_grid_set_column_spacing(GTK_GRID(hbox), 10);
1204 gtk_container_add(contain, hbox);
1205
1206 /* The label is set in city_dialog_update_building() */
1207 bar = gtk_progress_bar_new();
1208 gtk_widget_set_hexpand(bar, TRUE);
1209 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(bar), TRUE);
1210 pdialog->production.production_bar = bar;
1211 gtk_container_add(GTK_CONTAINER(hbox), bar);
1212 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), _("%d/%d %d turns"));
1213
1214 add_worklist_dnd_target(bar);
1215
1216 g_signal_connect(bar, "drag_data_received",
1217 G_CALLBACK(target_drag_data_received), pdialog);
1218
1219 pdialog->production.buy_command
1220 = icon_label_button_new("system-run", _("_Buy"));
1221 gtk_container_add(GTK_CONTAINER(hbox), GTK_WIDGET(pdialog->production.buy_command));
1222
1223 g_signal_connect(pdialog->production.buy_command, "clicked",
1224 G_CALLBACK(buy_callback), pdialog);
1225}
1226
1227/**********************************************************************/
1230 static void create_and_append_buildings_page(struct city_dialog *pdialog)
1231{
1232 if (low_citydlg) {
1233 GtkWidget *page;
1234 GtkWidget *label;
1235 GtkWidget *vbox;
1236 GtkWidget *view;
1237 const char *tab_title = _("Buildings");
1238
1239 page = gtk_grid_new();
1240 gtk_orientable_set_orientation(GTK_ORIENTABLE(page),
1241 GTK_ORIENTATION_VERTICAL);
1242 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
1243 label = gtk_label_new_with_mnemonic(tab_title);
1244
1245 create_production_header(pdialog, GTK_CONTAINER(page));
1246 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1247
1248 vbox = gtk_grid_new();
1249 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
1250 GTK_ORIENTATION_VERTICAL);
1251 gtk_container_add(GTK_CONTAINER(page), vbox);
1252
1253 view = create_citydlg_improvement_list(pdialog, vbox);
1254
1255 gtk_container_add(GTK_CONTAINER(vbox), view);
1256
1257 gtk_widget_show_all(page);
1258 }
1259}
1260
1261/**********************************************************************/
1264 static void create_and_append_worklist_page(struct city_dialog *pdialog)
1265{
1266 const char *tab_title = _("P_roduction");
1267 GtkWidget *label = gtk_label_new_with_mnemonic(tab_title);
1268 GtkWidget *page, *editor;
1269
1270 page = gtk_grid_new();
1271 gtk_orientable_set_orientation(GTK_ORIENTABLE(page),
1272 GTK_ORIENTATION_VERTICAL);
1273 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
1274 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1275
1276 /* stuff that's being currently built */
1277 if (!low_citydlg) {
1278 label = g_object_new(GTK_TYPE_LABEL,
1279 "label", _("Production:"),
1280 "xalign", 0.0, "yalign", 0.5, NULL);
1281 pdialog->production.production_label = label;
1282 gtk_container_add(GTK_CONTAINER(page), label);
1283
1284 create_production_header(pdialog, GTK_CONTAINER(page));
1285 } else {
1286 pdialog->production.production_label = NULL;
1287 }
1288
1289 editor = create_worklist();
1290 g_object_set(editor, "margin", 6, NULL);
1291 reset_city_worklist(editor, pdialog->pcity);
1292 gtk_container_add(GTK_CONTAINER(page), editor);
1293 pdialog->production.worklist = editor;
1294
1295 gtk_widget_show_all(page);
1296}
1297
1298/**********************************************************************/
1308 static void create_and_append_happiness_page(struct city_dialog *pdialog)
1309{
1310 GtkWidget *page, *label, *table, *right, *left, *frame;
1311 const char *tab_title = _("Happ_iness");
1312
1313 /* main page */
1314 page = gtk_grid_new();
1315 gtk_grid_set_column_spacing(GTK_GRID(page), 6);
1316 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
1317 label = gtk_label_new_with_mnemonic(tab_title);
1318 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1319
1320 /* left: info, citizens */
1321 left = gtk_grid_new();
1322 gtk_orientable_set_orientation(GTK_ORIENTABLE(left),
1323 GTK_ORIENTATION_VERTICAL);
1324 gtk_container_add(GTK_CONTAINER(page), left);
1325
1326 if (!low_citydlg) {
1327 /* upper left: info */
1328 frame = gtk_frame_new(_("Info"));
1329 gtk_container_add(GTK_CONTAINER(left), frame);
1330
1331 table = create_city_info_table(pdialog,
1332 pdialog->happiness.info_ebox,
1333 pdialog->happiness.info_label);
1334 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
1335 gtk_container_add(GTK_CONTAINER(frame), table);
1336 }
1337
1338 /* lower left: citizens */
1339 if (game.info.citizen_nationality) {
1340 pdialog->happiness.citizens = gtk_grid_new();
1341 gtk_orientable_set_orientation(
1342 GTK_ORIENTABLE(pdialog->happiness.citizens),
1343 GTK_ORIENTATION_VERTICAL);
1344 gtk_container_add(GTK_CONTAINER(left), pdialog->happiness.citizens);
1345 gtk_container_add(GTK_CONTAINER(pdialog->happiness.citizens),
1346 citizens_dialog_display(pdialog->pcity));
1347 }
1348
1349 /* right: city map, happiness */
1350 right = gtk_grid_new();
1351 gtk_orientable_set_orientation(GTK_ORIENTABLE(right),
1352 GTK_ORIENTATION_VERTICAL);
1353 gtk_container_add(GTK_CONTAINER(page), right);
1354
1355 if (!low_citydlg) {
1356 /* upper right: city map */
1357 frame = gtk_frame_new(_("City map"));
1358 gtk_widget_set_size_request(frame, CITY_MAP_MIN_SIZE_X,
1359 CITY_MAP_MIN_SIZE_Y);
1360 gtk_container_add(GTK_CONTAINER(right), frame);
1361
1362 city_dialog_map_create(pdialog, &pdialog->happiness.map_canvas);
1363 gtk_container_add(GTK_CONTAINER(frame), pdialog->happiness.map_canvas.sw);
1364 }
1365
1366 /* lower right: happiness */
1367 pdialog->happiness.widget = gtk_grid_new();
1368 gtk_orientable_set_orientation(GTK_ORIENTABLE(pdialog->happiness.widget),
1369 GTK_ORIENTATION_VERTICAL);
1370 gtk_container_add(GTK_CONTAINER(right), pdialog->happiness.widget);
1371 gtk_container_add(GTK_CONTAINER(pdialog->happiness.widget),
1372 get_top_happiness_display(pdialog->pcity, low_citydlg, pdialog->shell));
1373
1374 /* show page */
1375 gtk_widget_show_all(page);
1376}
1377
1378/**********************************************************************/
1381 static void create_and_append_cma_page(struct city_dialog *pdialog)
1382{
1383 GtkWidget *page, *label;
1384 const char *tab_title = _("_Governor");
1385
1386 page = gtk_grid_new();
1387
1388 label = gtk_label_new_with_mnemonic(tab_title);
1389
1390 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1391
1392 pdialog->cma_editor = create_cma_dialog(pdialog->pcity, low_citydlg);
1393 gtk_container_add(GTK_CONTAINER(page), pdialog->cma_editor->shell);
1394
1395 gtk_widget_show(page);
1396}
1397
1398/**********************************************************************/
1401 static void create_and_append_settings_page(struct city_dialog *pdialog)
1402{
1403 int i;
1404 GtkWidget *vbox2, *page, *frame, *label, *button;
1405 GtkSizeGroup *size;
1406 GSList *group;
1407 const char *tab_title = _("_Settings");
1408
1409 static const char *new_citizens_output_label[] = {
1410 N_("Luxury"),
1411 N_("Science"),
1412 N_("Gold")
1413 };
1414
1415 static const char *disband_label
1416 = N_("Allow unit production to disband city");
1417
1418 static const char *misc_whichtab_label[NUM_PAGES] = {
1419 N_("Overview page"),
1420 N_("Production page"),
1421 N_("Happiness page"),
1422 N_("Governor page"),
1423 N_("This Settings page"),
1424 N_("Last active page")
1425 };
1426
1427 static bool new_citizens_label_done;
1428 static bool misc_whichtab_label_done;
1429
1430 /* initialize signal_blocker */
1431 pdialog->misc.block_signal = 0;
1432
1433
1434 page = gtk_grid_new();
1435 gtk_grid_set_column_spacing(GTK_GRID(page), 18);
1436 gtk_container_set_border_width(GTK_CONTAINER(page), 8);
1437
1438 size = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
1439
1440 label = gtk_label_new_with_mnemonic(tab_title);
1441
1442 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
1443
1444 /* new_citizens radio */
1445 frame = gtk_frame_new(_("New citizens produce"));
1446 gtk_grid_attach(GTK_GRID(page), frame, 0, 0, 1, 1);
1447 gtk_size_group_add_widget(size, frame);
1448
1449 vbox2 = gtk_grid_new();
1450 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox2),
1451 GTK_ORIENTATION_VERTICAL);
1452 gtk_container_add(GTK_CONTAINER(frame), vbox2);
1453
1454 intl_slist(ARRAY_SIZE(new_citizens_output_label), new_citizens_output_label,
1455 &new_citizens_label_done);
1456
1457 group = NULL;
1458 for (i = 0; i < ARRAY_SIZE(new_citizens_output_label); i++) {
1459 button = gtk_radio_button_new_with_mnemonic(group, new_citizens_output_label[i]);
1460 pdialog->misc.new_citizens_radio[i] = button;
1461 gtk_container_add(GTK_CONTAINER(vbox2), button);
1462 g_signal_connect(button, "toggled",
1463 G_CALLBACK(cityopt_callback), pdialog);
1464 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1465 }
1466
1467 /* next is the next-time-open radio group in the right column */
1468 frame = gtk_frame_new(_("Next time open"));
1469 gtk_grid_attach(GTK_GRID(page), frame, 1, 0, 1, 1);
1470 gtk_size_group_add_widget(size, frame);
1471
1472 vbox2 = gtk_grid_new();
1473 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox2),
1474 GTK_ORIENTATION_VERTICAL);
1475 gtk_container_add(GTK_CONTAINER(frame), vbox2);
1476
1477 intl_slist(ARRAY_SIZE(misc_whichtab_label), misc_whichtab_label,
1478 &misc_whichtab_label_done);
1479
1480 group = NULL;
1481 for (i = 0; i < ARRAY_SIZE(misc_whichtab_label); i++) {
1482 button = gtk_radio_button_new_with_mnemonic(group, misc_whichtab_label[i]);
1483 pdialog->misc.whichtab_radio[i] = button;
1484 gtk_container_add(GTK_CONTAINER(vbox2), button);
1485 g_signal_connect(button, "toggled",
1486 G_CALLBACK(misc_whichtab_callback), GINT_TO_POINTER(i));
1487 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1488 }
1489
1490 /* now we go back and fill the hbox rename */
1491 frame = gtk_frame_new(_("City"));
1492 gtk_widget_set_margin_top(frame, 12);
1493 gtk_widget_set_margin_bottom(frame, 12);
1494 gtk_grid_attach(GTK_GRID(page), frame, 0, 1, 1, 1);
1495
1496 vbox2 = gtk_grid_new();
1497 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox2),
1498 GTK_ORIENTATION_VERTICAL);
1499 gtk_container_add(GTK_CONTAINER(frame), vbox2);
1500
1501 button = gtk_button_new_with_mnemonic(_("R_ename..."));
1502 pdialog->misc.rename_command = button;
1503 gtk_container_add(GTK_CONTAINER(vbox2), button);
1504 g_signal_connect(button, "clicked",
1505 G_CALLBACK(rename_callback), pdialog);
1506
1507 gtk_widget_set_sensitive(button, can_client_issue_orders());
1508
1509 /* the disband-city-on-unit-production button */
1510 button = gtk_check_button_new_with_mnemonic(_(disband_label));
1511 pdialog->misc.disband_on_settler = button;
1512 gtk_container_add(GTK_CONTAINER(vbox2), button);
1513 g_signal_connect(button, "toggled",
1514 G_CALLBACK(cityopt_callback), pdialog);
1515
1516 /* we choose which page to popup by default */
1517 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
1518 (pdialog->
1519 misc.whichtab_radio[new_dialog_def_page]),
1520 TRUE);
1521
1522 set_cityopt_values(pdialog);
1523
1524 gtk_widget_show_all(page);
1525
1526 if (new_dialog_def_page == (NUM_PAGES - 1)) {
1527 gtk_notebook_set_current_page(GTK_NOTEBOOK(pdialog->notebook),
1528 last_page);
1529 } else {
1530 gtk_notebook_set_current_page(GTK_NOTEBOOK(pdialog->notebook),
1531 new_dialog_def_page);
1532 }
1533}
1534
1535/**********************************************************************/
1543 static struct city_dialog *create_city_dialog(struct city *pcity)
1544{
1545 struct city_dialog *pdialog;
1546 GtkWidget *close_command;
1547 GtkWidget *vbox, *hbox, *cbox, *ebox;
1548 int citizen_bar_width;
1549 int citizen_bar_height;
1550 struct player *owner;
1551
1552 if (!city_dialogs_have_been_initialised) {
1553 initialize_city_dialogs();
1554 }
1555
1556 pdialog = fc_malloc(sizeof(struct city_dialog));
1557 pdialog->pcity = pcity;
1558 pdialog->sell_shell = NULL;
1559 pdialog->rename_shell = NULL;
1560 pdialog->happiness.map_canvas.sw = NULL; /* make sure NULL if spy */
1561 pdialog->happiness.map_canvas.ebox = NULL; /* ditto */
1562 pdialog->happiness.map_canvas.darea = NULL; /* ditto */
1563 pdialog->happiness.citizens = NULL; /* ditto */
1564 pdialog->production.buy_command = NULL;
1565 pdialog->production.production_label = NULL;
1566 pdialog->production.production_bar = NULL;
1567 pdialog->cma_editor = NULL;
1568 pdialog->map_canvas_store_unscaled
1569 = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1570 canvas_width, canvas_height);
1571
1572 pdialog->shell = gtk_dialog_new();
1573 gtk_window_set_title(GTK_WINDOW(pdialog->shell), city_name_get(pcity));
1574 setup_dialog(pdialog->shell, toplevel);
1575 gtk_window_set_role(GTK_WINDOW(pdialog->shell), "city");
1576
1577 g_signal_connect(pdialog->shell, "destroy",
1578 G_CALLBACK(city_destroy_callback), pdialog);
1579 gtk_window_set_position(GTK_WINDOW(pdialog->shell), GTK_WIN_POS_MOUSE);
1580 gtk_widget_set_name(pdialog->shell, "Freeciv");
1581
1582 gtk_widget_realize(pdialog->shell);
1583
1584 /* keep the icon of the executable on Windows (see PR#36491) */
1585#ifndef FREECIV_MSWINDOWS
1586 {
1587 GdkPixbuf *pixbuf = sprite_get_pixbuf(get_icon_sprite(tileset, ICON_CITYDLG));
1588
1589 /* Only call this after tileset_load_tiles is called. */
1590 gtk_window_set_icon(GTK_WINDOW(pdialog->shell), pixbuf);
1591 g_object_unref(pixbuf);
1592 }
1593#endif /* FREECIV_MSWINDOWS */
1594
1595 /* Restore size of the city dialog. */
1596 gtk_window_set_default_size(GTK_WINDOW(pdialog->shell),
1597 GUI_GTK_OPTION(citydlg_xsize),
1598 GUI_GTK_OPTION(citydlg_ysize));
1599
1600 pdialog->popup_menu = gtk_menu_new();
1601
1602 vbox = gtk_dialog_get_content_area(GTK_DIALOG(pdialog->shell));
1603 hbox = gtk_grid_new();
1604 gtk_grid_set_column_homogeneous(GTK_GRID(hbox), TRUE);
1605 gtk_container_add(GTK_CONTAINER(vbox), hbox);
1606
1607 /**** Citizens bar here ****/
1608 cbox = gtk_grid_new();
1609 gtk_container_add(GTK_CONTAINER(hbox), cbox);
1610
1611 ebox = gtk_event_box_new();
1612 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1613 gtk_container_add(GTK_CONTAINER(cbox), ebox);
1614
1615 citizen_bar_width = tileset_small_sprite_width(tileset) * NUM_CITIZENS_SHOWN;
1616 citizen_bar_height = tileset_small_sprite_height(tileset);
1617
1618 pdialog->citizen_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
1619 citizen_bar_width, citizen_bar_height);
1620 pdialog->citizen_images = gtk_image_new_from_surface(pdialog->citizen_surface);
1621
1622 gtk_widget_add_events(pdialog->citizen_images, GDK_BUTTON_PRESS_MASK);
1623 gtk_widget_set_margin_start(pdialog->citizen_images, 2);
1624 gtk_widget_set_margin_end(pdialog->citizen_images, 2);
1625 gtk_widget_set_margin_top(pdialog->citizen_images, 2);
1626 gtk_widget_set_margin_bottom(pdialog->citizen_images, 2);
1627 gtk_widget_set_halign(pdialog->citizen_images, GTK_ALIGN_START);
1628 gtk_widget_set_valign(pdialog->citizen_images, GTK_ALIGN_CENTER);
1629 gtk_container_add(GTK_CONTAINER(ebox), pdialog->citizen_images);
1630 g_signal_connect(G_OBJECT(ebox), "button-press-event",
1631 G_CALLBACK(citizens_callback), pdialog);
1632
1633 /**** City name label here ****/
1634 pdialog->name_label = gtk_label_new(NULL);
1635 gtk_widget_set_hexpand(pdialog->name_label, TRUE);
1636 gtk_widget_set_halign(pdialog->name_label, GTK_ALIGN_START);
1637 gtk_widget_set_valign(pdialog->name_label, GTK_ALIGN_CENTER);
1638 gtk_container_add(GTK_CONTAINER(hbox), pdialog->name_label);
1639
1640 /**** -Start of Notebook- ****/
1641
1642 pdialog->notebook = gtk_notebook_new();
1643 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(pdialog->notebook),
1644 GTK_POS_BOTTOM);
1645 gtk_container_add(GTK_CONTAINER(vbox), pdialog->notebook);
1646
1647 create_and_append_overview_page(pdialog);
1648 create_and_append_map_page(pdialog);
1649 create_and_append_buildings_page(pdialog);
1650
1651 owner = city_owner(pcity);
1652
1653 /* Only create these tabs if not a spy */
1654 if (owner == client_player() || client_is_global_observer()) {
1655 create_and_append_worklist_page(pdialog);
1656 create_and_append_happiness_page(pdialog);
1657 }
1658
1659 if (owner == client_player()
1660 && !client_is_observer()) {
1661 create_and_append_cma_page(pdialog);
1662 create_and_append_settings_page(pdialog);
1663 } else {
1664 gtk_notebook_set_current_page(GTK_NOTEBOOK(pdialog->notebook),
1665 OVERVIEW_PAGE);
1666 }
1667
1668 /**** End of Notebook ****/
1669
1670 /* bottom buttons */
1671
1672 pdialog->show_units_command =
1673 gtk_dialog_add_button(GTK_DIALOG(pdialog->shell), _("_List present units..."), CDLGR_UNITS);
1674
1675 g_signal_connect(GTK_DIALOG(pdialog->shell), "response",
1676 G_CALLBACK(citydlg_response_callback), pdialog);
1677
1678 pdialog->prev_command = gtk_button_new_from_icon_name("go-previous", 0);
1679 gtk_dialog_add_action_widget(GTK_DIALOG(pdialog->shell),
1680 GTK_WIDGET(pdialog->prev_command), 1);
1681
1682 pdialog->next_command = gtk_button_new_from_icon_name("go-next", 0);
1683 gtk_dialog_add_action_widget(GTK_DIALOG(pdialog->shell),
1684 GTK_WIDGET(pdialog->next_command), 2);
1685
1686 if (owner != client_player()) {
1687 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), FALSE);
1688 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), FALSE);
1689 }
1690
1691 close_command = gtk_dialog_add_button(GTK_DIALOG(pdialog->shell),
1692 _("_Close"), GTK_RESPONSE_CLOSE);
1693
1694 gtk_dialog_set_default_response(GTK_DIALOG(pdialog->shell),
1695 GTK_RESPONSE_CLOSE);
1696
1697 g_signal_connect(close_command, "clicked",
1698 G_CALLBACK(close_callback), pdialog);
1699
1700 g_signal_connect(pdialog->prev_command, "clicked",
1701 G_CALLBACK(switch_city_callback), pdialog);
1702
1703 g_signal_connect(pdialog->next_command, "clicked",
1704 G_CALLBACK(switch_city_callback), pdialog);
1705
1706 /* some other things we gotta do */
1707
1708 g_signal_connect(pdialog->shell, "key_press_event",
1709 G_CALLBACK(keyboard_handler), pdialog);
1710
1711 dialog_list_prepend(dialog_list, pdialog);
1712
1713 real_city_dialog_refresh(pdialog->pcity);
1714
1715 /* need to do this every time a new dialog is opened. */
1716 city_dialog_update_prev_next();
1717
1718 gtk_widget_show_all(pdialog->shell);
1719
1720 gtk_window_set_focus(GTK_WINDOW(pdialog->shell), close_command);
1721
1722 return pdialog;
1723}
1724
1725/**************** Functions to update parts of the dialog ****************/
1726/**********************************************************************/
1729 static void city_dialog_update_title(struct city_dialog *pdialog)
1730{
1731 gchar *buf;
1732 const gchar *now;
1733
1734 if (city_unhappy(pdialog->pcity)) {
1735 /* TRANS: city dialog title */
1736 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - DISORDER"),
1737 city_name_get(pdialog->pcity),
1738 population_to_text(city_population(pdialog->pcity)));
1739 } else if (city_celebrating(pdialog->pcity)) {
1740 /* TRANS: city dialog title */
1741 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - celebrating"),
1742 city_name_get(pdialog->pcity),
1743 population_to_text(city_population(pdialog->pcity)));
1744 } else if (city_happy(pdialog->pcity)) {
1745 /* TRANS: city dialog title */
1746 buf = g_strdup_printf(_("<b>%s</b> - %s citizens - happy"),
1747 city_name_get(pdialog->pcity),
1748 population_to_text(city_population(pdialog->pcity)));
1749 } else {
1750 /* TRANS: city dialog title */
1751 buf = g_strdup_printf(_("<b>%s</b> - %s citizens"),
1752 city_name_get(pdialog->pcity),
1753 population_to_text(city_population(pdialog->pcity)));
1754 }
1755
1756 now = gtk_label_get_text(GTK_LABEL(pdialog->name_label));
1757 if (strcmp(now, buf) != 0) {
1758 gtk_window_set_title(GTK_WINDOW(pdialog->shell), city_name_get(pdialog->pcity));
1759 gtk_label_set_markup(GTK_LABEL(pdialog->name_label), buf);
1760 }
1761
1762 g_free(buf);
1763}
1764
1765/**********************************************************************/
1768 static void city_dialog_update_citizens(struct city_dialog *pdialog)
1769{
1770 enum citizen_category categories[MAX_CITY_SIZE];
1771 int i, width, full_width, total_used_width;
1772 int citizen_bar_width, citizen_bar_height;
1773 struct city *pcity = pdialog->pcity;
1774 int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
1775 cairo_t *cr;
1776
1777 /* If there is not enough space we stack the icons. We draw from left to */
1778 /* right. width is how far we go to the right for each drawn pixmap. The */
1779 /* last icon is always drawn in full, and so has reserved */
1780 /* tileset_small_sprite_width(tileset) pixels. */
1781
1782 full_width = tileset_small_sprite_width(tileset);
1783 if (num_citizens > 1) {
1784 width = MIN(full_width, ((NUM_CITIZENS_SHOWN - 1) * full_width)
1785 / (num_citizens - 1));
1786 } else {
1787 width = full_width;
1788 }
1789 pdialog->cwidth = width;
1790
1791 /* overview page */
1792 /* keep these values in sync with create_city_dialog */
1793 citizen_bar_width = full_width * NUM_CITIZENS_SHOWN;
1794 citizen_bar_height = tileset_small_sprite_height(tileset);
1795
1796 cr = cairo_create(pdialog->citizen_surface);
1797
1798 for (i = 0; i < num_citizens; i++) {
1799 cairo_set_source_surface(cr,
1800 get_citizen_sprite(tileset, categories[i], i, pcity)->surface,
1801 i * width, 0);
1802 cairo_rectangle(cr, i * width, 0,
1803 /* Always draw last citizen in full */
1804 i + 1 < num_citizens ? width : full_width,
1805 citizen_bar_height);
1806 cairo_fill(cr);
1807 }
1808
1809 total_used_width = (i - 1) * width + full_width;
1810
1811 if (total_used_width < citizen_bar_width) {
1812 /* Clear the rest of the area.
1813 * Note that this might still be necessary even in cases where
1814 * num_citizens > NUM_CITIZENS_SHOWN, if the available width cannot be
1815 * divided perfectly. */
1816 cairo_rectangle(cr, total_used_width, 0,
1817 citizen_bar_width - total_used_width,
1818 citizen_bar_height);
1819 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
1820 cairo_fill(cr);
1821 }
1822
1823 cairo_destroy(cr);
1824
1825 gtk_widget_queue_draw(pdialog->citizen_images);
1826}
1827
1828/**********************************************************************/
1831 static void city_dialog_update_information(GtkWidget **info_ebox,
1832 GtkWidget **info_label,
1833 struct city_dialog *pdialog)
1834{
1835 int i, illness = 0;
1836 char buf[NUM_INFO_FIELDS][512];
1837 struct city *pcity = pdialog->pcity;
1838 int granaryturns;
1839 int non_workers = city_specialists(pcity);
1840
1841 /* fill the buffers with the necessary info */
1842 if (non_workers) {
1843 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
1844 pcity->size, non_workers);
1845 } else {
1846 fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d", pcity->size);
1847 }
1848 fc_snprintf(buf[INFO_FOOD], sizeof(buf[INFO_FOOD]), "%3d (%+4d)",
1849 pcity->prod[O_FOOD], pcity->surplus[O_FOOD]);
1850 fc_snprintf(buf[INFO_SHIELD], sizeof(buf[INFO_SHIELD]), "%3d (%+4d)",
1851 pcity->prod[O_SHIELD] + pcity->waste[O_SHIELD],
1852 pcity->surplus[O_SHIELD]);
1853 fc_snprintf(buf[INFO_TRADE], sizeof(buf[INFO_TRADE]), "%3d (%+4d)",
1854 pcity->surplus[O_TRADE] + pcity->waste[O_TRADE],
1855 pcity->surplus[O_TRADE]);
1856 fc_snprintf(buf[INFO_GOLD], sizeof(buf[INFO_GOLD]), "%3d (%+4d)",
1857 pcity->prod[O_GOLD], pcity->surplus[O_GOLD]);
1858 fc_snprintf(buf[INFO_LUXURY], sizeof(buf[INFO_LUXURY]), "%3d",
1859 pcity->prod[O_LUXURY]);
1860 fc_snprintf(buf[INFO_SCIENCE], sizeof(buf[INFO_SCIENCE]), "%3d",
1861 pcity->prod[O_SCIENCE]);
1862 fc_snprintf(buf[INFO_GRANARY], sizeof(buf[INFO_GRANARY]), "%4d/%-4d",
1863 pcity->food_stock, city_granary_size(city_size_get(pcity)));
1864
1865 granaryturns = city_turns_to_grow(pcity);
1866 if (granaryturns == 0) {
1867 /* TRANS: city growth is blocked. Keep short. */
1868 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("blocked"));
1869 } else if (granaryturns == FC_INFINITY) {
1870 /* TRANS: city is not growing. Keep short. */
1871 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]), _("never"));
1872 } else {
1873 /* A negative value means we'll have famine in that many turns.
1874 But that's handled down below. */
1875 /* TRANS: city growth turns. Keep short. */
1876 fc_snprintf(buf[INFO_GROWTH], sizeof(buf[INFO_GROWTH]),
1877 PL_("%d turn", "%d turns", abs(granaryturns)),
1878 abs(granaryturns));
1879 }
1880 fc_snprintf(buf[INFO_CORRUPTION], sizeof(buf[INFO_CORRUPTION]), "%4d",
1881 pcity->waste[O_TRADE]);
1882 fc_snprintf(buf[INFO_WASTE], sizeof(buf[INFO_WASTE]), "%4d",
1883 pcity->waste[O_SHIELD]);
1884 fc_snprintf(buf[INFO_CULTURE], sizeof(buf[INFO_CULTURE]), "%4d",
1885 pcity->client.culture);
1886 fc_snprintf(buf[INFO_POLLUTION], sizeof(buf[INFO_POLLUTION]), "%4d",
1887 pcity->pollution);
1888 if (!game.info.illness_on) {
1889 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), " -.-");
1890 } else {
1891 illness = city_illness_calc(pcity, NULL, NULL, NULL, NULL);
1892 /* illness is in tenth of percent */
1893 fc_snprintf(buf[INFO_ILLNESS], sizeof(buf[INFO_ILLNESS]), "%5.1f%%",
1894 (float)illness / 10.0);
1895 }
1896 if (pcity->steal) {
1897 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), PL_("%d time", "%d times", pcity->steal),
1898 pcity->steal);
1899 } else {
1900 fc_snprintf(buf[INFO_STEAL], sizeof(buf[INFO_STEAL]), _("Not stolen"));
1901 }
1902
1903 get_city_dialog_airlift_value(pcity, buf[INFO_AIRLIFT], sizeof(buf[INFO_AIRLIFT]));
1904
1905 /* stick 'em in the labels */
1906 for (i = 0; i < NUM_INFO_FIELDS; i++) {
1907 gtk_label_set_text(GTK_LABEL(info_label[i]), buf[i]);
1908 }
1909
1910 /*
1911 * Make use of the emergency-indicating styles set up for certain labels
1912 * in create_city_info_table().
1913 */
1914 /* For starvation, the "4" below is arbitrary. 3 turns should be enough
1915 * of a warning. */
1916 if (granaryturns > -4 && granaryturns < 0) {
1917 gtk_style_context_add_class(gtk_widget_get_style_context(info_label[INFO_GRANARY]), "emergency");
1918 } else {
1919 gtk_style_context_remove_class(gtk_widget_get_style_context(info_label[INFO_GRANARY]), "emergency");
1920 }
1921
1922 if (granaryturns == 0 || pcity->surplus[O_FOOD] < 0) {
1923 gtk_style_context_add_class(gtk_widget_get_style_context(info_label[INFO_GROWTH]), "emergency");
1924 } else {
1925 gtk_style_context_remove_class(gtk_widget_get_style_context(info_label[INFO_GROWTH]), "emergency");
1926 }
1927
1928 /* someone could add the color &orange for better granularity here */
1929 if (pcity->pollution >= 10) {
1930 gtk_style_context_add_class(gtk_widget_get_style_context(info_label[INFO_POLLUTION]), "emergency");
1931 } else {
1932 gtk_style_context_remove_class(gtk_widget_get_style_context(info_label[INFO_POLLUTION]), "emergency");
1933 }
1934
1935 /* illness is in tenth of percent, i.e 100 == 10.0% */
1936 if (illness >= 100) {
1937 gtk_style_context_add_class(gtk_widget_get_style_context(info_label[INFO_ILLNESS]), "emergency");
1938 } else {
1939 gtk_style_context_remove_class(gtk_widget_get_style_context(info_label[INFO_ILLNESS]), "emergency");
1940 }
1941}
1942
1943/**********************************************************************/
1946 static void city_dialog_update_map(struct city_dialog *pdialog)
1947{
1948 struct canvas store = FC_STATIC_CANVAS_INIT;
1949
1950 store.surface = pdialog->map_canvas_store_unscaled;
1951
1952 /* The drawing is done in three steps.
1953 * 1. First we render to a pixmap with the appropriate canvas size.
1954 * 2. Then the pixmap is rendered into a pixbuf of equal size.
1955 * 3. Finally this pixbuf is composited and scaled onto the GtkImage's
1956 * target pixbuf.
1957 */
1958
1959 city_dialog_redraw_map(pdialog->pcity, &store);
1960
1961 /* draw to real window */
1962 draw_map_canvas(pdialog);
1963}
1964
1965/**********************************************************************/
1968 static void city_dialog_update_building(struct city_dialog *pdialog)
1969{
1970 char buf[32], buf2[200];
1971 gdouble pct;
1972
1973 GtkListStore* store;
1974 GtkTreeIter iter;
1975 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
1976 struct item items[MAX_NUM_PRODUCTION_TARGETS];
1977 int targets_used, item;
1978 struct city *pcity = pdialog->pcity;
1979 gboolean sensitive = city_can_buy(pcity);
1980 const char *descr = city_production_name_translation(pcity);
1981 int cost = city_production_build_shield_cost(pcity);
1982
1983 if (pdialog->overview.buy_command != NULL) {
1984 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->overview.buy_command), sensitive);
1985 }
1986 if (pdialog->production.buy_command != NULL) {
1987 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->production.buy_command), sensitive);
1988 }
1989
1990 /* Make sure build slots info is up to date */
1991 if (pdialog->production.production_label != NULL) {
1992 int build_slots = city_build_slots(pcity);
1993
1994 /* Only display extra info if more than one slot is available */
1995 if (build_slots > 1) {
1996 fc_snprintf(buf2, sizeof(buf2),
1997 /* TRANS: never actually used with built_slots <= 1 */
1998 PL_("Production (up to %d unit per turn):",
1999 "Production (up to %d units per turn):", build_slots),
2000 build_slots);
2001 gtk_label_set_text(
2002 GTK_LABEL(pdialog->production.production_label), buf2);
2003 } else {
2004 gtk_label_set_text(
2005 GTK_LABEL(pdialog->production.production_label), _("Production:"));
2006 }
2007 }
2008
2009 /* Update what the city is working on */
2010 get_city_dialog_production(pcity, buf, sizeof(buf));
2011
2012 if (cost > 0) {
2013 pct = (gdouble) pcity->shield_stock / (gdouble) cost;
2014 pct = CLAMP(pct, 0.0, 1.0);
2015 } else {
2016 pct = 1.0;
2017 }
2018
2019 if (pdialog->overview.production_bar != NULL) {
2020 fc_snprintf(buf2, sizeof(buf2), "%s%s\n%s", descr,
2021 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2022 gtk_progress_bar_set_text(
2023 GTK_PROGRESS_BAR(pdialog->overview.production_bar), buf2);
2024 gtk_progress_bar_set_fraction(
2025 GTK_PROGRESS_BAR(pdialog->overview.production_bar), pct);
2026 }
2027
2028 if (pdialog->production.production_bar != NULL) {
2029 fc_snprintf(buf2, sizeof(buf2), "%s%s: %s", descr,
2030 worklist_is_empty(&pcity->worklist) ? "" : " (+)", buf);
2031 gtk_progress_bar_set_text(
2032 GTK_PROGRESS_BAR(pdialog->production.production_bar), buf2);
2033 gtk_progress_bar_set_fraction(
2034 GTK_PROGRESS_BAR(pdialog->production.production_bar), pct);
2035 }
2036
2037 if (pdialog->overview.production_combo != NULL) {
2038 gtk_combo_box_set_active(GTK_COMBO_BOX(pdialog->overview.production_combo),
2039 -1);
2040 }
2041
2042 store = pdialog->overview.change_production_store;
2043 if (store != NULL) {
2044 gtk_list_store_clear(pdialog->overview.change_production_store);
2045
2046 targets_used
2047 = collect_eventually_buildable_targets(targets, pdialog->pcity, FALSE);
2048 name_and_sort_items(targets, targets_used, items, FALSE, pcity);
2049
2050 for (item = 0; item < targets_used; item++) {
2051 if (can_city_build_now(pcity, &items[item].item)) {
2052 const char *name;
2053 struct sprite* sprite;
2054 GdkPixbuf *pix;
2055 struct universal target = items[item].item;
2056 bool useless;
2057
2058 if (VUT_UTYPE == target.kind) {
2059 name = utype_name_translation(target.value.utype);
2060 sprite = get_unittype_sprite(tileset, target.value.utype,
2061 direction8_invalid());
2062 useless = FALSE;
2063 } else {
2064 name = improvement_name_translation(target.value.building);
2065 sprite = get_building_sprite(tileset, target.value.building);
2066 useless = is_improvement_redundant(pcity, target.value.building);
2067 }
2068 pix = sprite_get_pixbuf(sprite);
2069 gtk_list_store_append(store, &iter);
2070 gtk_list_store_set(store, &iter, 0, pix,
2071 1, name, 3, useless,
2072 2, (gint)cid_encode(items[item].item), -1);
2073 g_object_unref(G_OBJECT(pix));
2074 }
2075 }
2076 }
2077
2078 /* work around GTK+ refresh bug. */
2079 if (pdialog->overview.production_bar != NULL) {
2080 gtk_widget_queue_resize(pdialog->overview.production_bar);
2081 }
2082 if (pdialog->production.production_bar != NULL) {
2083 gtk_widget_queue_resize(pdialog->production.production_bar);
2084 }
2085}
2086
2087/**********************************************************************/
2090 static void city_dialog_update_improvement_list(struct city_dialog *pdialog)
2091{
2092 int item, targets_used;
2093 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2094 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2095 GtkTreeModel *model;
2096 GtkListStore *store;
2097
2098 const char *tooltip_sellable = _("Press <b>ENTER</b> or double-click to "
2099 "sell an improvement.");
2100 const char *tooltip_great_wonder = _("Great Wonder - cannot be sold.");
2101 const char *tooltip_small_wonder = _("Small Wonder - cannot be sold.");
2102
2103 model =
2104 gtk_tree_view_get_model(GTK_TREE_VIEW(pdialog->overview.improvement_list));
2105 store = GTK_LIST_STORE(model);
2106
2107 targets_used = collect_already_built_targets(targets, pdialog->pcity);
2108 name_and_sort_items(targets, targets_used, items, FALSE, pdialog->pcity);
2109
2110 gtk_list_store_clear(store);
2111
2112 for (item = 0; item < targets_used; item++) {
2113 GdkPixbuf *pix;
2114 GtkTreeIter it;
2115 int upkeep;
2116 struct sprite *sprite;
2117 struct universal target = items[item].item;
2118
2119 fc_assert_action(VUT_IMPROVEMENT == target.kind, continue);
2120 /* This takes effects (like Adam Smith's) into account. */
2121 upkeep = city_improvement_upkeep(pdialog->pcity, target.value.building);
2122 sprite = get_building_sprite(tileset, target.value.building);
2123
2124 pix = sprite_get_pixbuf(sprite);
2125 gtk_list_store_append(store, &it);
2126 gtk_list_store_set(store, &it,
2127 0, target.value.building,
2128 1, pix,
2129 2, items[item].descr,
2130 3, upkeep,
2131 4,
2132 is_improvement_redundant(pdialog->pcity,
2133 target.value.building),
2134 5,
2135 is_great_wonder(target.value.building) ?
2136 tooltip_great_wonder :
2137 (is_small_wonder(target.value.building) ?
2138 tooltip_small_wonder : tooltip_sellable),
2139 -1);
2140 g_object_unref(G_OBJECT(pix));
2141 }
2142}
2143
2144/**********************************************************************/
2147 static void city_dialog_update_supported_units(struct city_dialog *pdialog)
2148{
2149 struct unit_list *units;
2150 struct unit_node_vector *nodes;
2151 int n, m, i;
2152 gchar *buf;
2153 int free_unhappy = get_city_bonus(pdialog->pcity, EFT_MAKE_CONTENT_MIL);
2154
2155 if (NULL != client.conn.playing
2156 && city_owner(pdialog->pcity) != client.conn.playing) {
2157 units = pdialog->pcity->client.info_units_supported;
2158 } else {
2159 units = pdialog->pcity->units_supported;
2160 }
2161
2162 nodes = &pdialog->overview.supported_units;
2163
2164 n = unit_list_size(units);
2165 m = unit_node_vector_size(nodes);
2166
2167 if (m > n) {
2168 i = 0;
2169 unit_node_vector_iterate(nodes, elt) {
2170 if (i++ >= n) {
2171 gtk_widget_destroy(elt->cmd);
2172 }
2173 } unit_node_vector_iterate_end;
2174
2175 unit_node_vector_reserve(nodes, n);
2176 } else {
2177 for (i = m; i < n; i++) {
2178 GtkWidget *cmd, *pix;
2179 struct unit_node node;
2180
2181 cmd = gtk_button_new();
2182 node.cmd = cmd;
2183
2184 gtk_button_set_relief(GTK_BUTTON(cmd), GTK_RELIEF_NONE);
2185 gtk_widget_add_events(cmd,
2186 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
2187
2188 pix = gtk_image_new();
2189 node.pix = pix;
2190 node.height = tileset_unit_with_upkeep_height(tileset);
2191
2192 gtk_container_add(GTK_CONTAINER(cmd), pix);
2193
2194 gtk_grid_attach(GTK_GRID(pdialog->overview.supported_unit_table),
2195 cmd, i, 0, 1, 1);
2196 unit_node_vector_append(nodes, node);
2197 }
2198 }
2199
2200 i = 0;
2201 unit_list_iterate(units, punit) {
2202 struct unit_node *pnode;
2203 int happy_cost = city_unit_unhappiness(punit, &free_unhappy);
2204
2205 pnode = unit_node_vector_get(nodes, i);
2206 if (pnode) {
2207 GtkWidget *cmd, *pix;
2208
2209 cmd = pnode->cmd;
2210 pix = pnode->pix;
2211
2212 put_unit_image_city_overlays(punit, GTK_IMAGE(pix), pnode->height,
2213 punit->upkeep, happy_cost);
2214
2215 g_signal_handlers_disconnect_matched(cmd,
2216 G_SIGNAL_MATCH_FUNC,
2217 0, 0, NULL, supported_unit_callback, NULL);
2218
2219 g_signal_handlers_disconnect_matched(cmd,
2220 G_SIGNAL_MATCH_FUNC,
2221 0, 0, NULL, supported_unit_middle_callback, NULL);
2222
2223 gtk_widget_set_tooltip_text(cmd, unit_description(punit));
2224
2225 g_signal_connect(cmd, "button_press_event",
2226 G_CALLBACK(supported_unit_callback),
2227 GINT_TO_POINTER(punit->id));
2228
2229 g_signal_connect(cmd, "button_release_event",
2230 G_CALLBACK(supported_unit_middle_callback),
2231 GINT_TO_POINTER(punit->id));
2232
2233 if (city_owner(pdialog->pcity) != client.conn.playing) {
2234 gtk_widget_set_sensitive(cmd, FALSE);
2235 } else {
2236 gtk_widget_set_sensitive(cmd, TRUE);
2237 }
2238
2239 gtk_widget_show(pix);
2240 gtk_widget_show(cmd);
2241 }
2242 i++;
2243 } unit_list_iterate_end;
2244
2245 buf = g_strdup_printf(_("Supported units %d"), n);
2246 gtk_frame_set_label(GTK_FRAME(pdialog->overview.supported_units_frame), buf);
2247 g_free(buf);
2248}
2249
2250/**********************************************************************/
2253 static void city_dialog_update_present_units(struct city_dialog *pdialog)
2254{
2255 struct unit_list *units;
2256 struct unit_node_vector *nodes;
2257 int n, m, i;
2258 gchar *buf;
2259
2260 if (NULL != client.conn.playing
2261 && city_owner(pdialog->pcity) != client.conn.playing) {
2262 units = pdialog->pcity->client.info_units_present;
2263 } else {
2264 units = pdialog->pcity->tile->units;
2265 }
2266
2267 nodes = &pdialog->overview.present_units;
2268
2269 n = unit_list_size(units);
2270 m = unit_node_vector_size(nodes);
2271
2272 if (m > n) {
2273 i = 0;
2274 unit_node_vector_iterate(nodes, elt) {
2275 if (i++ >= n) {
2276 gtk_widget_destroy(elt->cmd);
2277 }
2278 } unit_node_vector_iterate_end;
2279
2280 unit_node_vector_reserve(nodes, n);
2281 } else {
2282 for (i = m; i < n; i++) {
2283 GtkWidget *cmd, *pix;
2284 struct unit_node node;
2285
2286 cmd = gtk_button_new();
2287 node.cmd = cmd;
2288
2289 gtk_button_set_relief(GTK_BUTTON(cmd), GTK_RELIEF_NONE);
2290 gtk_widget_add_events(cmd,
2291 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
2292
2293 pix = gtk_image_new();
2294 node.pix = pix;
2295 node.height = tileset_full_tile_height(tileset);
2296
2297 gtk_container_add(GTK_CONTAINER(cmd), pix);
2298
2299 gtk_grid_attach(GTK_GRID(pdialog->overview.present_unit_table),
2300 cmd, i, 0, 1, 1);
2301 unit_node_vector_append(nodes, node);
2302 }
2303 }
2304
2305 i = 0;
2306 unit_list_iterate(units, punit) {
2307 struct unit_node *pnode;
2308
2309 pnode = unit_node_vector_get(nodes, i);
2310 if (pnode) {
2311 GtkWidget *cmd, *pix;
2312
2313 cmd = pnode->cmd;
2314 pix = pnode->pix;
2315
2316 put_unit_image(punit, GTK_IMAGE(pix), pnode->height);
2317
2318 g_signal_handlers_disconnect_matched(cmd,
2319 G_SIGNAL_MATCH_FUNC,
2320 0, 0, NULL, present_unit_callback, NULL);
2321
2322 g_signal_handlers_disconnect_matched(cmd,
2323 G_SIGNAL_MATCH_FUNC,
2324 0, 0, NULL, present_unit_middle_callback, NULL);
2325
2326 gtk_widget_set_tooltip_text(cmd, unit_description(punit));
2327
2328 g_signal_connect(cmd, "button_press_event",
2329 G_CALLBACK(present_unit_callback),
2330 GINT_TO_POINTER(punit->id));
2331
2332 g_signal_connect(cmd, "button_release_event",
2333 G_CALLBACK(present_unit_middle_callback),
2334 GINT_TO_POINTER(punit->id));
2335
2336 if (city_owner(pdialog->pcity) != client.conn.playing) {
2337 gtk_widget_set_sensitive(cmd, FALSE);
2338 } else {
2339 gtk_widget_set_sensitive(cmd, TRUE);
2340 }
2341
2342 gtk_widget_show(pix);
2343 gtk_widget_show(cmd);
2344 }
2345 i++;
2346 } unit_list_iterate_end;
2347
2348 buf = g_strdup_printf(_("Present units %d"), n);
2349 gtk_frame_set_label(GTK_FRAME(pdialog->overview.present_units_frame), buf);
2350 g_free(buf);
2351}
2352
2353/**********************************************************************/
2360 static void city_dialog_update_prev_next(void)
2361{
2362 int count = 0;
2363 int city_number;
2364
2365 if (NULL != client.conn.playing) {
2366 city_number = city_list_size(client.conn.playing->cities);
2367 } else {
2368 city_number = FC_INFINITY; /* ? */
2369 }
2370
2371 /* the first time, we see if all the city dialogs are open */
2372
2373 dialog_list_iterate(dialog_list, pdialog) {
2374 if (city_owner(pdialog->pcity) == client.conn.playing)
2375 count++;
2376 }
2377 dialog_list_iterate_end;
2378
2379 if (count == city_number) { /* all are open, shouldn't prev/next */
2380 dialog_list_iterate(dialog_list, pdialog) {
2381 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), FALSE);
2382 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), FALSE);
2383 }
2384 dialog_list_iterate_end;
2385 } else {
2386 dialog_list_iterate(dialog_list, pdialog) {
2387 if (city_owner(pdialog->pcity) == client.conn.playing) {
2388 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->prev_command), TRUE);
2389 gtk_widget_set_sensitive(GTK_WIDGET(pdialog->next_command), TRUE);
2390 }
2391 }
2392 dialog_list_iterate_end;
2393 }
2394}
2395
2396/**********************************************************************/
2399 static void citydlg_response_callback(GtkDialog *dlg, gint response,
2400 void *data)
2401{
2402 switch (response) {
2403 case CDLGR_UNITS:
2404 show_units_response(data);
2405 break;
2406 }
2407}
2408
2409/**********************************************************************/
2412 static void show_units_response(void *data)
2413{
2414 struct city_dialog *pdialog = (struct city_dialog *) data;
2415 struct tile *ptile = pdialog->pcity->tile;
2416
2417 if (unit_list_size(ptile->units)) {
2418 unit_select_dialog_popup(ptile);
2419 }
2420}
2421
2422/**********************************************************************/
2425 static void destroy_func(GtkWidget *w, gpointer data)
2426{
2427 gtk_widget_destroy(w);
2428}
2429
2430/**********************************************************************/
2433 static gboolean supported_unit_callback(GtkWidget *w, GdkEventButton *ev,
2434 gpointer data)
2435{
2436 GtkWidget *menu, *item;
2437 struct city_dialog *pdialog;
2438 struct city *pcity;
2439 struct unit *punit =
2440 player_unit_by_number(client_player(), (size_t) data);
2441
2442 if (NULL != punit
2443 && NULL != (pcity = game_city_by_number(punit->homecity))
2444 && NULL != (pdialog = get_city_dialog(pcity))) {
2445
2446 if (ev->type != GDK_BUTTON_PRESS || ev->button == 2 || ev->button == 3
2447 || !can_client_issue_orders()) {
2448 return FALSE;
2449 }
2450
2451 menu = pdialog->popup_menu;
2452
2453 gtk_menu_popdown(GTK_MENU(menu));
2454 gtk_container_foreach(GTK_CONTAINER(menu), destroy_func, NULL);
2455
2456 item = gtk_menu_item_new_with_mnemonic(_("Cen_ter"));
2457 g_signal_connect(item, "activate",
2458 G_CALLBACK(unit_center_callback),
2459 GINT_TO_POINTER(punit->id));
2460 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2461
2462 item = gtk_menu_item_new_with_mnemonic(_("_Activate unit"));
2463 g_signal_connect(item, "activate",
2464 G_CALLBACK(unit_activate_callback),
2465 GINT_TO_POINTER(punit->id));
2466 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2467
2468 item = gtk_menu_item_new_with_mnemonic(_("Activate unit, _close dialog"));
2469 g_signal_connect(item, "activate",
2470 G_CALLBACK(supported_unit_activate_close_callback),
2471 GINT_TO_POINTER(punit->id));
2472 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2473
2474 item = gtk_menu_item_new_with_mnemonic(_("_Disband unit"));
2475 g_signal_connect(item, "activate",
2476 G_CALLBACK(unit_disband_callback),
2477 GINT_TO_POINTER(punit->id));
2478 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2479
2480 if (!unit_can_do_action(punit, ACTION_DISBAND_UNIT)) {
2481 gtk_widget_set_sensitive(item, FALSE);
2482 }
2483
2484 gtk_widget_show_all(menu);
2485
2486 gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
2487 }
2488
2489 return TRUE;
2490}
2491
2492/**********************************************************************/
2495 static gboolean present_unit_callback(GtkWidget *w, GdkEventButton *ev,
2496 gpointer data)
2497{
2498 GtkWidget *menu, *item;
2499 struct city_dialog *pdialog;
2500 struct city *pcity;
2501 struct unit *punit =
2502 player_unit_by_number(client_player(), (size_t) data);
2503
2504 if (NULL != punit
2505 && NULL != (pcity = tile_city(unit_tile(punit)))
2506 && NULL != (pdialog = get_city_dialog(pcity))) {
2507
2508 if (ev->type != GDK_BUTTON_PRESS || ev->button == 2 || ev->button == 3
2509 || !can_client_issue_orders()) {
2510 return FALSE;
2511 }
2512
2513 menu = pdialog->popup_menu;
2514
2515 gtk_menu_popdown(GTK_MENU(menu));
2516 gtk_container_foreach(GTK_CONTAINER(menu), destroy_func, NULL);
2517
2518 item = gtk_menu_item_new_with_mnemonic(_("_Activate unit"));
2519 g_signal_connect(item, "activate",
2520 G_CALLBACK(unit_activate_callback),
2521 GINT_TO_POINTER(punit->id));
2522 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2523
2524 item = gtk_menu_item_new_with_mnemonic(_("Activate unit, _close dialog"));
2525 g_signal_connect(item, "activate",
2526 G_CALLBACK(present_unit_activate_close_callback),
2527 GINT_TO_POINTER(punit->id));
2528 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2529
2530 item = gtk_menu_item_new_with_mnemonic(_("_Load unit"));
2531 g_signal_connect(item, "activate",
2532 G_CALLBACK(unit_load_callback),
2533 GINT_TO_POINTER(punit->id));
2534 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2535
2536 if (!unit_can_load(punit)) {
2537 gtk_widget_set_sensitive(item, FALSE);
2538 }
2539
2540 item = gtk_menu_item_new_with_mnemonic(_("_Unload unit"));
2541 g_signal_connect(item, "activate",
2542 G_CALLBACK(unit_unload_callback),
2543 GINT_TO_POINTER(punit->id));
2544 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2545
2546 if (!can_unit_unload(punit, unit_transport_get(punit))
2547 || !can_unit_exist_at_tile(&(wld.map), punit, unit_tile(punit))) {
2548 gtk_widget_set_sensitive(item, FALSE);
2549 }
2550
2551 item = gtk_menu_item_new_with_mnemonic(_("_Sentry unit"));
2552 g_signal_connect(item, "activate",
2553 G_CALLBACK(unit_sentry_callback),
2554 GINT_TO_POINTER(punit->id));
2555 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2556
2557 if (punit->activity == ACTIVITY_SENTRY
2558 || !can_unit_do_activity_client(punit, ACTIVITY_SENTRY)) {
2559 gtk_widget_set_sensitive(item, FALSE);
2560 }
2561
2562 item = gtk_menu_item_new_with_mnemonic(_("_Fortify unit"));
2563 g_signal_connect(item, "activate",
2564 G_CALLBACK(unit_fortify_callback),
2565 GINT_TO_POINTER(punit->id));
2566 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2567
2568 if (punit->activity == ACTIVITY_FORTIFYING
2569 || !can_unit_do_activity_client(punit, ACTIVITY_FORTIFYING)) {
2570 gtk_widget_set_sensitive(item, FALSE);
2571 }
2572
2573 item = gtk_menu_item_new_with_mnemonic(_("_Disband unit"));
2574 g_signal_connect(item, "activate",
2575 G_CALLBACK(unit_disband_callback),
2576 GINT_TO_POINTER(punit->id));
2577 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2578
2579 if (!unit_can_do_action(punit, ACTION_DISBAND_UNIT)) {
2580 gtk_widget_set_sensitive(item, FALSE);
2581 }
2582
2583 item = gtk_menu_item_new_with_mnemonic(
2584 action_id_name_translation(ACTION_HOME_CITY));
2585 g_signal_connect(item, "activate",
2586 G_CALLBACK(unit_homecity_callback),
2587 GINT_TO_POINTER(punit->id));
2588 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2589 gtk_widget_set_sensitive(item, can_unit_change_homecity_to(punit, pcity));
2590
2591 item = gtk_menu_item_new_with_mnemonic(_("U_pgrade unit"));
2592 gtk_widget_set_sensitive(item, action_ever_possible(ACTION_UPGRADE_UNIT));
2593 g_signal_connect(item, "activate",
2594 G_CALLBACK(unit_upgrade_callback),
2595 GINT_TO_POINTER(punit->id));
2596 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2597
2598 if (!can_client_issue_orders()
2599 || NULL == can_upgrade_unittype(client.conn.playing,
2600 unit_type_get(punit))) {
2601 gtk_widget_set_sensitive(item, FALSE);
2602 }
2603
2604 gtk_widget_show_all(menu);
2605
2606 gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
2607 }
2608
2609 return TRUE;
2610}
2611
2612/**********************************************************************/
2615 static gboolean present_unit_middle_callback(GtkWidget *w,
2616 GdkEventButton *ev,
2617 gpointer data)
2618{
2619 struct city_dialog *pdialog;
2620 struct city *pcity;
2621 struct unit *punit =
2622 player_unit_by_number(client_player(), (size_t) data);
2623
2624 if (NULL != punit
2625 && NULL != (pcity = tile_city(unit_tile(punit)))
2626 && NULL != (pdialog = get_city_dialog(pcity))
2627 && can_client_issue_orders()) {
2628
2629 if (ev->button == 3) {
2630 unit_focus_set(punit);
2631 } else if (ev->button == 2) {
2632 unit_focus_set(punit);
2633 close_city_dialog(pdialog);
2634 }
2635 }
2636
2637 return TRUE;
2638}
2639
2640/**********************************************************************/
2643 static gboolean supported_unit_middle_callback(GtkWidget *w,
2644 GdkEventButton *ev,
2645 gpointer data)
2646{
2647 struct city_dialog *pdialog;
2648 struct city *pcity;
2649 struct unit *punit =
2650 player_unit_by_number(client_player(), (size_t) data);
2651
2652 if (NULL != punit
2653 && NULL != (pcity = game_city_by_number(punit->homecity))
2654 && NULL != (pdialog = get_city_dialog(pcity))
2655 && can_client_issue_orders()) {
2656
2657 if (ev->button == 3) {
2658 unit_focus_set(punit);
2659 } else if (ev->button == 2) {
2660 unit_focus_set(punit);
2661 close_city_dialog(pdialog);
2662 }
2663 }
2664
2665 return TRUE;
2666}
2667
2668/**********************************************************************/
2671 static void unit_center_callback(GtkWidget *w, gpointer data)
2672{
2673 struct unit *punit =
2674 player_unit_by_number(client_player(), (size_t)data);
2675
2676 if (NULL != punit) {
2677 center_tile_mapcanvas(unit_tile(punit));
2678 }
2679}
2680
2681/**********************************************************************/
2684 static void unit_activate_callback(GtkWidget *w, gpointer data)
2685{
2686 struct unit *punit =
2687 player_unit_by_number(client_player(), (size_t)data);
2688
2689 if (NULL != punit) {
2690 unit_focus_set(punit);
2691 }
2692}
2693
2694/**********************************************************************/
2698 static void supported_unit_activate_close_callback(GtkWidget *w,
2699 gpointer data)
2700{
2701 struct unit *punit =
2702 player_unit_by_number(client_player(), (size_t)data);
2703
2704 if (NULL != punit) {
2705 struct city *pcity =
2706 player_city_by_number(client_player(), punit->homecity);
2707
2708 unit_focus_set(punit);
2709 if (NULL != pcity) {
2710 struct city_dialog *pdialog = get_city_dialog(pcity);
2711
2712 if (NULL != pdialog) {
2713 close_city_dialog(pdialog);
2714 }
2715 }
2716 }
2717}
2718
2719/**********************************************************************/
2723 static void present_unit_activate_close_callback(GtkWidget *w,
2724 gpointer data)
2725{
2726 struct unit *punit =
2727 player_unit_by_number(client_player(), (size_t)data);
2728
2729 if (NULL != punit) {
2730 struct city *pcity = tile_city(unit_tile(punit));
2731
2732 unit_focus_set(punit);
2733 if (NULL != pcity) {
2734 struct city_dialog *pdialog = get_city_dialog(pcity);
2735
2736 if (NULL != pdialog) {
2737 close_city_dialog(pdialog);
2738 }
2739 }
2740 }
2741}
2742
2743/**********************************************************************/
2746 static void unit_load_callback(GtkWidget *w, gpointer data)
2747{
2748 struct unit *punit =
2749 player_unit_by_number(client_player(), (size_t)data);
2750
2751 if (NULL != punit) {
2752 request_transport(punit, unit_tile(punit));
2753 }
2754}
2755
2756/**********************************************************************/
2759 static void unit_unload_callback(GtkWidget *w, gpointer data)
2760{
2761 struct unit *punit =
2762 player_unit_by_number(client_player(), (size_t)data);
2763
2764 if (NULL != punit) {
2765 request_unit_unload(punit);
2766 }
2767}
2768
2769/**********************************************************************/
2772 static void unit_sentry_callback(GtkWidget *w, gpointer data)
2773{
2774 struct unit *punit =
2775 player_unit_by_number(client_player(), (size_t)data);
2776
2777 if (NULL != punit) {
2778 request_unit_sentry(punit);
2779 }
2780}
2781
2782/**********************************************************************/
2785 static void unit_fortify_callback(GtkWidget *w, gpointer data)
2786{
2787 struct unit *punit =
2788 player_unit_by_number(client_player(), (size_t)data);
2789
2790 if (NULL != punit) {
2791 request_unit_fortify(punit);
2792 }
2793}
2794
2795/**********************************************************************/
2798 static void unit_disband_callback(GtkWidget *w, gpointer data)
2799{
2800 struct unit_list *punits;
2801 struct unit *punit =
2802 player_unit_by_number(client_player(), (size_t)data);
2803
2804 if (NULL == punit) {
2805 return;
2806 }
2807
2808 punits = unit_list_new();
2809 unit_list_append(punits, punit);
2810 popup_disband_dialog(punits);
2811 unit_list_destroy(punits);
2812}
2813
2814/**********************************************************************/
2818 static void unit_homecity_callback(GtkWidget *w, gpointer data)
2819{
2820 struct unit *punit =
2821 player_unit_by_number(client_player(), (size_t)data);
2822
2823 if (NULL != punit) {
2824 request_unit_change_homecity(punit);
2825 }
2826}
2827
2828/**********************************************************************/
2831 static void unit_upgrade_callback(GtkWidget *w, gpointer data)
2832{
2833 struct unit_list *punits;
2834 struct unit *punit =
2835 player_unit_by_number(client_player(), (size_t)data);
2836
2837 if (NULL == punit) {
2838 return;
2839 }
2840
2841 punits = unit_list_new();
2842 unit_list_append(punits, punit);
2843 popup_upgrade_dialog(punits);
2844 unit_list_destroy(punits);
2845}
2846
2847/******** Callbacks for citizen bar, map funcs that are not update *******/
2848/**********************************************************************/
2852 static gboolean citizens_callback(GtkWidget *w, GdkEventButton *ev,
2853 gpointer data)
2854{
2855 struct city_dialog *pdialog = data;
2856 struct city *pcity = pdialog->pcity;
2857 int citnum, tlen, len;
2858
2859 if (!can_client_issue_orders()) {
2860 return FALSE;
2861 }
2862
2863 tlen = tileset_small_sprite_width(tileset);
2864 len = (city_size_get(pcity) - 1) * pdialog->cwidth + tlen;
2865 if (ev->x > len) {
2866 /* no citizen that far to the right */
2867 return FALSE;
2868 }
2869 citnum = MIN(city_size_get(pcity) - 1, ev->x / pdialog->cwidth);
2870
2871 city_rotate_specialist(pcity, citnum);
2872
2873 return TRUE;
2874}
2875
2876/**********************************************************************/
2879 static void set_city_workertask(GtkWidget *w, gpointer data)
2880{
2881 enum unit_activity act = (enum unit_activity)GPOINTER_TO_INT(data);
2882 struct city *pcity = workertask_req.owner;
2883 struct tile *ptile = workertask_req.loc;
2884 struct packet_worker_task task;
2885
2886 task.city_id32 = pcity->id;
2887 task.city_id16 = task.city_id32;
2888
2889 if (act == ACTIVITY_LAST) {
2890 task.tgt = -1;
2891 task.want = 0;
2892 } else {
2893 enum extra_cause cause = activity_to_extra_cause(act);
2894 enum extra_rmcause rmcause = activity_to_extra_rmcause(act);
2895 struct extra_type *tgt;
2896
2897 if (cause != EC_NONE) {
2898 tgt = next_extra_for_tile(ptile, cause, city_owner(pcity), NULL);
2899 } else if (rmcause != ERM_NONE) {
2900 tgt = prev_extra_in_tile(ptile, rmcause, city_owner(pcity), NULL);
2901 } else {
2902 tgt = NULL;
2903 }
2904
2905 if (tgt == NULL) {
2906 struct terrain *pterr = tile_terrain(ptile);
2907
2908 if ((act != ACTIVITY_TRANSFORM
2909 || pterr->transform_result == NULL || pterr->transform_result == pterr)
2910 && (act != ACTIVITY_CULTIVATE || pterr->cultivate_result == NULL)
2911 && (act != ACTIVITY_PLANT || pterr->plant_result == NULL)) {
2912 /* No extra to order */
2913 output_window_append(ftc_client, _("There's no suitable extra to order."));
2914
2915 return;
2916 }
2917
2918 task.tgt = -1;
2919 } else {
2920 task.tgt = extra_index(tgt);
2921 }
2922
2923 task.want = 100;
2924 }
2925
2926 task.tile_id = ptile->index;
2927 task.activity = act;
2928
2929 send_packet_worker_task(&client.conn, &task);
2930}
2931
2932/**********************************************************************/
2935 static void workertask_dlg_destroy(GtkWidget *w, gpointer data)
2936{
2937 is_showing_workertask_dialog = FALSE;
2938}
2939
2940/**********************************************************************/
2943 static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
2944{
2945 if (!is_showing_workertask_dialog) {
2946 GtkWidget *shl;
2947 struct terrain *pterr = tile_terrain(ptile);
2948 struct universal for_terr = { .kind = VUT_TERRAIN,
2949 .value = { .terrain = pterr }};
2950 struct worker_task *ptask;
2951
2952 is_showing_workertask_dialog = TRUE;
2953 workertask_req.owner = pcity;
2954 workertask_req.loc = ptile;
2955
2956 shl = choice_dialog_start(GTK_WINDOW(toplevel),
2957 _("What Action to Request"),
2958 _("Select autosettler activity:"));
2959
2960 ptask = worker_task_list_get(pcity->task_reqs, 0);
2961 if (ptask != NULL) {
2962 choice_dialog_add(shl, _("Clear request"),
2963 G_CALLBACK(set_city_workertask),
2964 GINT_TO_POINTER(ACTIVITY_LAST), FALSE, NULL);
2965 }
2966
2967 if (action_id_univs_not_blocking(ACTION_MINE, NULL, &for_terr)) {
2968 choice_dialog_add(shl, Q_("?act:Mine"),
2969 G_CALLBACK(set_city_workertask),
2970 GINT_TO_POINTER(ACTIVITY_MINE), FALSE, NULL);
2971 }
2972 if (pterr->plant_result != NULL
2973 && action_id_univs_not_blocking(ACTION_PLANT,
2974 NULL, &for_terr)) {
2975 choice_dialog_add(shl, _("Plant"),
2976 G_CALLBACK(set_city_workertask),
2977 GINT_TO_POINTER(ACTIVITY_PLANT), FALSE, NULL);
2978 }
2979 if (action_id_univs_not_blocking(ACTION_IRRIGATE, NULL, &for_terr)) {
2980 choice_dialog_add(shl, _("Irrigate"),
2981 G_CALLBACK(set_city_workertask),
2982 GINT_TO_POINTER(ACTIVITY_IRRIGATE), FALSE, NULL);
2983 }
2984 if (pterr->cultivate_result != NULL
2985 && action_id_univs_not_blocking(ACTION_CULTIVATE,
2986 NULL, &for_terr)) {
2987 choice_dialog_add(shl, _("Cultivate"),
2988 G_CALLBACK(set_city_workertask),
2989 GINT_TO_POINTER(ACTIVITY_CULTIVATE), FALSE, NULL);
2990 }
2991 if (next_extra_for_tile(ptile, EC_ROAD, city_owner(pcity), NULL) != NULL) {
2992 choice_dialog_add(shl, _("Road"),
2993 G_CALLBACK(set_city_workertask),
2994 GINT_TO_POINTER(ACTIVITY_GEN_ROAD), FALSE, NULL);
2995 }
2996 if (pterr->transform_result != pterr && pterr->transform_result != NULL
2997 && action_id_univs_not_blocking(ACTION_TRANSFORM_TERRAIN,
2998 NULL, &for_terr)) {
2999 choice_dialog_add(shl, _("Transform"),
3000 G_CALLBACK(set_city_workertask),
3001 GINT_TO_POINTER(ACTIVITY_TRANSFORM), FALSE, NULL);
3002 }
3003 if (prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION,
3004 city_owner(pcity), NULL) != NULL) {
3005 choice_dialog_add(shl, _("Clean Pollution"),
3006 G_CALLBACK(set_city_workertask),
3007 GINT_TO_POINTER(ACTIVITY_POLLUTION), FALSE, NULL);
3008 }
3009 if (prev_extra_in_tile(ptile, ERM_CLEANFALLOUT,
3010 city_owner(pcity), NULL) != NULL) {
3011 choice_dialog_add(shl, _("Clean Fallout"),
3012 G_CALLBACK(set_city_workertask),
3013 GINT_TO_POINTER(ACTIVITY_FALLOUT), FALSE, NULL);
3014 }
3015
3016 choice_dialog_add(shl, _("_Cancel"), 0, 0, FALSE, NULL);
3017 choice_dialog_end(shl);
3018
3019 g_signal_connect(shl, "destroy", G_CALLBACK(workertask_dlg_destroy),
3020 NULL);
3021 }
3022}
3023
3024/**********************************************************************/
3027 static gboolean button_down_citymap(GtkWidget *w, GdkEventButton *ev,
3028 gpointer data)
3029{
3030 struct city_dialog *pdialog = data;
3031 int canvas_x, canvas_y, city_x, city_y;
3032
3033 if (!can_client_issue_orders()) {
3034 return FALSE;
3035 }
3036
3037 if (ev->button == 1 && cma_is_city_under_agent(pdialog->pcity, NULL)) {
3038 return FALSE;
3039 }
3040
3041 canvas_x = ev->x * (double)canvas_width / (double)CITYMAP_WIDTH;
3042 canvas_y = ev->y * (double)canvas_height / (double)CITYMAP_HEIGHT;
3043
3044 if (canvas_to_city_pos(&city_x, &city_y,
3045 city_map_radius_sq_get(pdialog->pcity),
3046 canvas_x, canvas_y)) {
3047 if (ev->button == 1) {
3048 city_toggle_worker(pdialog->pcity, city_x, city_y);
3049 } else if (ev->button == 3) {
3050 struct city *pcity = pdialog->pcity;
3051
3052 popup_workertask_dlg(pdialog->pcity,
3053 city_map_to_tile(&(wld.map), pcity->tile,
3054 city_map_radius_sq_get(pcity),
3055 city_x, city_y));
3056 }
3057 }
3058
3059 return TRUE;
3060}
3061
3062/**********************************************************************/
3065 static void draw_map_canvas(struct city_dialog *pdialog)
3066{
3067 gtk_widget_queue_draw(pdialog->overview.map_canvas.darea);
3068 if (pdialog->happiness.map_canvas.darea) { /* in case of spy */
3069 gtk_widget_queue_draw(pdialog->happiness.map_canvas.darea);
3070 }
3071}
3072
3073/************** Callbacks for Buy, Change, Sell, Worklist ****************/
3074/**********************************************************************/
3077 static void buy_callback_response(GtkWidget *w, gint response, gpointer data)
3078{
3079 struct city_dialog *pdialog = data;
3080
3081 if (response == GTK_RESPONSE_YES) {
3082 city_buy_production(pdialog->pcity);
3083 }
3084 gtk_widget_destroy(w);
3085}
3086
3087/**********************************************************************/
3090 static void buy_callback(GtkWidget *w, gpointer data)
3091{
3092 GtkWidget *shell;
3093 struct city_dialog *pdialog = data;
3094 const char *name = city_production_name_translation(pdialog->pcity);
3095 int value = pdialog->pcity->client.buy_cost;
3096 char buf[1024];
3097
3098 if (!can_client_issue_orders()) {
3099 return;
3100 }
3101
3102 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
3103 "Treasury contains %d gold.",
3104 client_player()->economic.gold),
3105 client_player()->economic.gold);
3106
3107 if (value <= client_player()->economic.gold) {
3108 shell = gtk_message_dialog_new(NULL,
3109 GTK_DIALOG_DESTROY_WITH_PARENT,
3110 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
3111 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3112 PL_("Buy %s for %d gold?\n%s",
3113 "Buy %s for %d gold?\n%s", value),
3114 name, value, buf);
3115 setup_dialog(shell, pdialog->shell);
3116 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3117 gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_NO);
3118 g_signal_connect(shell, "response", G_CALLBACK(buy_callback_response),
3119 pdialog);
3120 gtk_window_present(GTK_WINDOW(shell));
3121 } else {
3122 shell = gtk_message_dialog_new(NULL,
3123 GTK_DIALOG_DESTROY_WITH_PARENT,
3124 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
3125 /* TRANS: Last %s is pre-pluralised "Treasury contains %d gold." */
3126 PL_("%s costs %d gold.\n%s",
3127 "%s costs %d gold.\n%s", value),
3128 name, value, buf);
3129 setup_dialog(shell, pdialog->shell);
3130 gtk_window_set_title(GTK_WINDOW(shell), _("Buy It!"));
3131 g_signal_connect(shell, "response", G_CALLBACK(gtk_widget_destroy),
3132 NULL);
3133 gtk_window_present(GTK_WINDOW(shell));
3134 }
3135}
3136
3137/**********************************************************************/
3140 static void change_production_callback(GtkComboBox *combo,
3141 struct city_dialog *pdialog)
3142{
3143 GtkTreeIter iter;
3144
3145 if (can_client_issue_orders()
3146 && gtk_combo_box_get_active_iter(combo, &iter)) {
3147 cid id;
3148 struct universal univ;
3149
3150 gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter, 2, &id, -1);
3151 univ = cid_production(id);
3152 city_change_production(pdialog->pcity, &univ);
3153 }
3154}
3155
3156/**********************************************************************/
3159 static void sell_callback(struct impr_type *pimprove, gpointer data)
3160{
3161 GtkWidget *shl;
3162 struct city_dialog *pdialog = (struct city_dialog *) data;
3163 pdialog->sell_id = improvement_number(pimprove);
3164 int price;
3165
3166 if (!can_client_issue_orders()) {
3167 return;
3168 }
3169
3170 if (test_player_sell_building_now(client.conn.playing, pdialog->pcity,
3171 pimprove) != TR_SUCCESS) {
3172 return;
3173 }
3174
3175 price = impr_sell_gold(pimprove);
3176 shl = gtk_message_dialog_new(NULL,
3177 GTK_DIALOG_DESTROY_WITH_PARENT,
3178 GTK_MESSAGE_QUESTION,
3179 GTK_BUTTONS_YES_NO,
3180 PL_("Sell %s for %d gold?",
3181 "Sell %s for %d gold?", price),
3182 city_improvement_name_translation(pdialog->pcity, pimprove), price);
3183 setup_dialog(shl, pdialog->shell);
3184 pdialog->sell_shell = shl;
3185
3186 gtk_window_set_title(GTK_WINDOW(shl), _("Sell It!"));
3187 gtk_window_set_position(GTK_WINDOW(shl), GTK_WIN_POS_CENTER_ON_PARENT);
3188
3189 g_signal_connect(shl, "response",
3190 G_CALLBACK(sell_callback_response), pdialog);
3191
3192 gtk_window_present(GTK_WINDOW(shl));
3193}
3194
3195/**********************************************************************/
3198 static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
3199{
3200 struct city_dialog *pdialog = data;
3201
3202 if (response == GTK_RESPONSE_YES) {
3203 city_sell_improvement(pdialog->pcity, pdialog->sell_id);
3204 }
3205 gtk_widget_destroy(w);
3206
3207 pdialog->sell_shell = NULL;
3208}
3209
3210/**********************************************************************/
3213 static void impr_callback(GtkTreeView *view, GtkTreePath *path,
3214 GtkTreeViewColumn *col, gpointer data)
3215{
3216 GtkTreeModel *model;
3217 GtkTreeIter it;
3218 GdkWindow *win;
3219 GdkSeat *seat;
3220 GdkModifierType mask;
3221 struct impr_type *pimprove;
3222
3223 model = gtk_tree_view_get_model(view);
3224
3225 if (!gtk_tree_model_get_iter(model, &it, path)) {
3226 return;
3227 }
3228
3229 gtk_tree_model_get(model, &it, 0, &pimprove, -1);
3230
3231 win = gtk_widget_get_parent_window(GTK_WIDGET(view));
3232 seat = gdk_display_get_default_seat(gdk_window_get_display(win));
3233
3234 gdk_window_get_device_position(win, gdk_seat_get_pointer(seat),
3235 NULL, NULL, &mask);
3236
3237 if (!(mask & GDK_CONTROL_MASK)) {
3238 sell_callback(pimprove, data);
3239 } else {
3240 if (is_great_wonder(pimprove)) {
3241 popup_help_dialog_typed(improvement_name_translation(pimprove), HELP_WONDER);
3242 } else {
3243 popup_help_dialog_typed(improvement_name_translation(pimprove), HELP_IMPROVEMENT);
3244 }
3245 }
3246}
3247
3248/************ Callbacks for stuff on the Misc. Settings page *************/
3249/**********************************************************************/
3252 static void rename_callback(GtkWidget *w, gpointer data)
3253{
3254 struct city_dialog *pdialog;
3255
3256 pdialog = (struct city_dialog *) data;
3257
3258 pdialog->rename_shell = input_dialog_create(GTK_WINDOW(pdialog->shell),
3259 /* "shellrenamecity" */
3260 _("Rename City"),
3261 _("What should we rename the city to?"),
3262 city_name_get(pdialog->pcity),
3263 rename_popup_callback, pdialog);
3264}
3265
3266/**********************************************************************/
3269 static void rename_popup_callback(gpointer data, gint response,
3270 const char *input)
3271{
3272 struct city_dialog *pdialog = data;
3273
3274 if (pdialog) {
3275 if (response == GTK_RESPONSE_OK) {
3276 city_rename(pdialog->pcity, input);
3277 } /* else CANCEL or DELETE_EVENT */
3278
3279 pdialog->rename_shell = NULL;
3280 }
3281}
3282
3283/**********************************************************************/
3286 static void misc_whichtab_callback(GtkWidget * w, gpointer data)
3287{
3288 new_dialog_def_page = GPOINTER_TO_INT(data);
3289}
3290
3291/**********************************************************************/
3294 static void cityopt_callback(GtkWidget * w, gpointer data)
3295{
3296 struct city_dialog *pdialog = (struct city_dialog *) data;
3297
3298 if (!can_client_issue_orders()) {
3299 return;
3300 }
3301
3302 if (!pdialog->misc.block_signal) {
3303 struct city *pcity = pdialog->pcity;
3304 bv_city_options new_options;
3305
3306 fc_assert(CITYO_LAST == 3);
3307
3308 BV_CLR_ALL(new_options);
3309 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->misc.disband_on_settler))) {
3310 BV_SET(new_options, CITYO_DISBAND);
3311 }
3312 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->misc.new_citizens_radio[1]))) {
3313 BV_SET(new_options, CITYO_SCIENCE_SPECIALISTS);
3314 }
3315 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->misc.new_citizens_radio[2]))) {
3316 BV_SET(new_options, CITYO_GOLD_SPECIALISTS);
3317 }
3318
3319 dsend_packet_city_options_req(&client.conn, pcity->id, pcity->id, new_options);
3320 }
3321}
3322
3323/**********************************************************************/
3327 static void set_cityopt_values(struct city_dialog *pdialog)
3328{
3329 struct city *pcity = pdialog->pcity;
3330
3331 pdialog->misc.block_signal = 1;
3332
3333 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->misc.disband_on_settler),
3334 is_city_option_set(pcity, CITYO_DISBAND));
3335
3336 if (is_city_option_set(pcity, CITYO_SCIENCE_SPECIALISTS)) {
3337 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
3338 (pdialog->misc.new_citizens_radio[1]), TRUE);
3339 } else if (is_city_option_set(pcity, CITYO_GOLD_SPECIALISTS)) {
3340 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
3341 (pdialog->misc.new_citizens_radio[2]), TRUE);
3342 } else {
3343 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
3344 (pdialog->misc.new_citizens_radio[0]), TRUE);
3345 }
3346 pdialog->misc.block_signal = 0;
3347}
3348
3349/******************** Callbacks for: Close, Prev, Next. ******************/
3350/**********************************************************************/
3353 static void close_callback(GtkWidget *w, gpointer data)
3354{
3355 close_city_dialog((struct city_dialog *) data);
3356}
3357
3358/**********************************************************************/
3361 static void city_destroy_callback(GtkWidget *w, gpointer data)
3362{
3363 struct city_dialog *pdialog;
3364
3365 pdialog = (struct city_dialog *) data;
3366
3367 gtk_widget_hide(pdialog->shell);
3368
3369 if (game.info.citizen_nationality) {
3370 citizens_dialog_close(pdialog->pcity);
3371 }
3372 close_happiness_dialog(pdialog->pcity);
3373 close_cma_dialog(pdialog->pcity);
3374
3375 /* Save size of the city dialog. */
3376 GUI_GTK_OPTION(citydlg_xsize)
3377 = CLIP(GUI_GTK3_22_CITYDLG_MIN_XSIZE,
3378 gtk_widget_get_allocated_width(pdialog->shell),
3379 GUI_GTK3_22_CITYDLG_MAX_XSIZE);
3380 GUI_GTK_OPTION(citydlg_ysize)
3381 = CLIP(GUI_GTK3_22_CITYDLG_MIN_XSIZE,
3382 gtk_widget_get_allocated_height(pdialog->shell),
3383 GUI_GTK3_22_CITYDLG_MAX_XSIZE);
3384
3385 last_page
3386 = gtk_notebook_get_current_page(GTK_NOTEBOOK(pdialog->notebook));
3387
3388 if (pdialog->popup_menu) {
3389 gtk_widget_destroy(pdialog->popup_menu);
3390 }
3391
3392 dialog_list_remove(dialog_list, pdialog);
3393
3394 unit_node_vector_free(&pdialog->overview.supported_units);
3395 unit_node_vector_free(&pdialog->overview.present_units);
3396
3397 if (pdialog->sell_shell) {
3398 gtk_widget_destroy(pdialog->sell_shell);
3399 }
3400 if (pdialog->rename_shell) {
3401 gtk_widget_destroy(pdialog->rename_shell);
3402 }
3403
3404 cairo_surface_destroy(pdialog->map_canvas_store_unscaled);
3405 cairo_surface_destroy(pdialog->citizen_surface);
3406
3407 free(pdialog);
3408
3409 /* need to do this every time a new dialog is closed. */
3410 city_dialog_update_prev_next();
3411}
3412
3413/**********************************************************************/
3416 static void close_city_dialog(struct city_dialog *pdialog)
3417{
3418 gtk_widget_destroy(pdialog->shell);
3419}
3420
3421/**********************************************************************/
3425 static void switch_city_callback(GtkWidget *w, gpointer data)
3426{
3427 struct city_dialog *pdialog = (struct city_dialog *) data;
3428 int i, j, dir, size;
3429 struct city *new_pcity = NULL;
3430
3431 if (client_is_global_observer()) {
3432 return;
3433 }
3434
3435 size = city_list_size(client.conn.playing->cities);
3436
3437 fc_assert_ret(city_dialogs_have_been_initialised);
3438 fc_assert_ret(size >= 1);
3439 fc_assert_ret(city_owner(pdialog->pcity) == client.conn.playing);
3440
3441 if (size == 1) {
3442 return;
3443 }
3444
3445 /* dir = 1 will advance to the city, dir = -1 will get previous */
3446 if (w == GTK_WIDGET(pdialog->next_command)) {
3447 dir = 1;
3448 } else if (w == GTK_WIDGET(pdialog->prev_command)) {
3449 dir = -1;
3450 } else {
3451 /* Always fails. */
3452 fc_assert_ret(w == GTK_WIDGET(pdialog->next_command)
3453 || w == GTK_WIDGET(pdialog->prev_command));
3454 dir = 1;
3455 }
3456
3457 for (i = 0; i < size; i++) {
3458 if (pdialog->pcity == city_list_get(client.conn.playing->cities, i)) {
3459 break;
3460 }
3461 }
3462
3463 fc_assert_ret(i < size);
3464
3465 for (j = 1; j < size; j++) {
3466 struct city *other_pcity = city_list_get(client.conn.playing->cities,
3467 (i + dir * j + size) % size);
3468 struct city_dialog *other_pdialog = get_city_dialog(other_pcity);
3469
3470 fc_assert_ret(other_pdialog != pdialog);
3471 if (!other_pdialog) {
3472 new_pcity = other_pcity;
3473 break;
3474 }
3475 }
3476
3477 if (!new_pcity) {
3478 /* Every other city has an open city dialog. */
3479 return;
3480 }
3481
3482 /* cleanup happiness dialog */
3483 if (game.info.citizen_nationality) {
3484 citizens_dialog_close(pdialog->pcity);
3485 }
3486 close_happiness_dialog(pdialog->pcity);
3487
3488 pdialog->pcity = new_pcity;
3489
3490 /* reinitialize happiness, and cma dialogs */
3491 if (game.info.citizen_nationality) {
3492 gtk_container_add(GTK_CONTAINER(pdialog->happiness.citizens),
3493 citizens_dialog_display(pdialog->pcity));
3494 }
3495 gtk_container_add(GTK_CONTAINER(pdialog->happiness.widget),
3496 get_top_happiness_display(pdialog->pcity, low_citydlg, pdialog->shell));
3497 if (!client_is_observer()) {
3498 fc_assert(pdialog->cma_editor != NULL);
3499 pdialog->cma_editor->pcity = new_pcity;
3500 }
3501
3502 reset_city_worklist(pdialog->production.worklist, pdialog->pcity);
3503
3504 can_slide = FALSE;
3505 center_tile_mapcanvas(pdialog->pcity->tile);
3506 can_slide = TRUE;
3507 if (!client_is_observer()) {
3508 set_cityopt_values(pdialog); /* need not be in real_city_dialog_refresh */
3509 }
3510
3511 real_city_dialog_refresh(pdialog->pcity);
3512
3513 /* recenter the city map(s) */
3514 city_dialog_map_recenter(pdialog->overview.map_canvas.sw);
3515 if (pdialog->happiness.map_canvas.sw) {
3516 city_dialog_map_recenter(pdialog->happiness.map_canvas.sw);
3517 }
3518}
action_id_name_translation
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1910
action_ever_possible
bool action_ever_possible(action_id action)
Definition actions.c:9311
action_id_univs_not_blocking
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:947
n
#define n
Definition astring.c:77
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
height
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
canvas_y
struct canvas int int canvas_y
Definition canvas_g.h:43
canvas_x
struct canvas int canvas_x
Definition canvas_g.h:43
width
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
output_window_append
void output_window_append(const struct ft_color color, const char *featured_text)
Definition chatline_common.c:104
chatline_common.h
city_improvement_name_translation
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:657
city_production_build_shield_cost
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:721
city_granary_size
int city_granary_size(int city_size)
Definition city.c:2095
can_city_build_now
bool can_city_build_now(const struct city *pcity, const struct universal *target)
Definition city.c:984
city_unit_unhappiness
int city_unit_unhappiness(struct unit *punit, int *free_unhappy)
Definition city.c:2934
city_build_slots
int city_build_slots(const struct city *pcity)
Definition city.c:2825
city_map_to_tile
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:299
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1106
city_improvement_upkeep
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1222
is_city_option_set
bool is_city_option_set(const struct city *pcity, enum city_options option)
Definition city.c:3289
city_population
int city_population(const struct city *pcity)
Definition city.c:1160
city_unhappy
bool city_unhappy(const struct city *pcity)
Definition city.c:1591
city_celebrating
bool city_celebrating(const struct city *pcity)
Definition city.c:1610
city_illness_calc
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2763
city_happy
bool city_happy(const struct city *pcity)
Definition city.c:1579
city_map_radius_sq_get
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:131
city_specialists
citizens city_specialists(const struct city *pcity)
Definition city.c:3218
city_turns_to_grow
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1961
city_production_name_translation
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:694
city.h
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
citizen_category
citizen_category
Definition city.h:259
city_owner
#define city_owner(_pcity_)
Definition city.h:543
MAX_CITY_SIZE
#define MAX_CITY_SIZE
Definition city.h:98
FEELING_FINAL
@ FEELING_FINAL
Definition city.h:276
get_city_dialog_output_text
void get_city_dialog_output_text(const struct city *pcity, Output_type_id otype, char *buf, size_t bufsz)
Definition citydlg_common.c:733
get_city_dialog_production
void get_city_dialog_production(struct city *pcity, char *buffer, size_t buffer_len)
Definition citydlg_common.c:260
city_rename
int city_rename(struct city *pcity, const char *name)
Definition citydlg_common.c:1577
get_city_citizen_types
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx, enum citizen_category *categories)
Definition citydlg_common.c:1175
city_buy_production
int city_buy_production(struct city *pcity)
Definition citydlg_common.c:1525
city_toggle_worker
int city_toggle_worker(struct city *pcity, int city_x, int city_y)
Definition citydlg_common.c:1545
get_city_dialog_airlift_text
void get_city_dialog_airlift_text(const struct city *pcity, char *buf, size_t bufsz)
Definition citydlg_common.c:1043
city_change_production
int city_change_production(struct city *pcity, struct universal *target)
Definition citydlg_common.c:1261
city_rotate_specialist
void city_rotate_specialist(struct city *pcity, int citizen_index)
Definition citydlg_common.c:1212
get_citydlg_canvas_width
int get_citydlg_canvas_width(void)
Definition citydlg_common.c:51
canvas_to_city_pos
bool canvas_to_city_pos(int *city_x, int *city_y, int city_radius_sq, int canvas_x, int canvas_y)
Definition citydlg_common.c:115
get_city_dialog_airlift_value
void get_city_dialog_airlift_value(const struct city *pcity, char *buf, size_t bufsz)
Definition citydlg_common.c:1113
city_dialog_redraw_map
void city_dialog_redraw_map(struct city *pcity, struct canvas *pcanvas)
Definition citydlg_common.c:187
city_sell_improvement
int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
Definition citydlg_common.c:1517
get_city_dialog_pollution_text
void get_city_dialog_pollution_text(const struct city *pcity, char *buf, size_t bufsz)
Definition citydlg_common.c:967
get_city_dialog_culture_text
void get_city_dialog_culture_text(const struct city *pcity, char *buf, size_t bufsz)
Definition citydlg_common.c:993
city_can_buy
bool city_can_buy(const struct city *pcity)
Definition citydlg_common.c:1497
get_citydlg_canvas_height
int get_citydlg_canvas_height(void)
Definition citydlg_common.c:59
get_city_dialog_illness_text
void get_city_dialog_illness_text(const struct city *pcity, char *buf, size_t bufsz)
Definition citydlg_common.c:895
city_report_dialog_update_city
void city_report_dialog_update_city(struct city *pcity)
Definition update_queue.c:641
client_is_global_observer
bool client_is_global_observer(void)
Definition client_main.c:1346
client_is_observer
bool client_is_observer(void)
Definition client_main.c:1086
client
struct civclient client
Definition client_main.c:149
can_client_issue_orders
bool can_client_issue_orders(void)
Definition client_main.c:1265
client_has_player
bool client_has_player(void)
Definition client_main.c:1365
client_main.h
client_player
#define client_player()
Definition client_main.h:106
climap.h
collect_eventually_buildable_targets
int collect_eventually_buildable_targets(struct universal *targets, struct city *pcity, bool advanced_tech)
Definition climisc.c:802
name_and_sort_items
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:633
cid_encode
cid cid_encode(struct universal target)
Definition climisc.c:475
collect_already_built_targets
int collect_already_built_targets(struct universal *targets, struct city *pcity)
Definition climisc.c:895
MAX_NUM_PRODUCTION_TARGETS
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:87
cid_production
#define cid_production
Definition climisc.h:71
cid
int cid
Definition climisc.h:31
cma_is_city_under_agent
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:550
cma_fec.h
request_unit_fortify
void request_unit_fortify(struct unit *punit)
Definition control.c:2211
unit_focus_set
void unit_focus_set(struct unit *punit)
Definition control.c:502
request_unit_change_homecity
void request_unit_change_homecity(struct unit *punit)
Definition control.c:1992
request_unit_unload
void request_unit_unload(struct unit *pcargo)
Definition control.c:2090
request_unit_sentry
void request_unit_sentry(struct unit *punit)
Definition control.c:2200
control.h
can_unit_do_activity_client
#define can_unit_do_activity_client(_punit_, _act_)
Definition control.h:40
punit
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
cost
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
id
int int id
Definition editgui_g.h:28
editor
static struct editor_state * editor
Definition editor.c:100
get_city_bonus
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:789
event
enum event_type event
Definition events.c:81
next_extra_for_tile
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:740
prev_extra_in_tile
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:765
activity_to_extra_cause
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1028
activity_to_extra_rmcause
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1049
extra_index
#define extra_index(_e_)
Definition extras.h:177
Impr_type_id
int Impr_type_id
Definition fc_types.h:346
EC_NONE
#define EC_NONE
Definition fc_types.h:967
TR_SUCCESS
@ TR_SUCCESS
Definition fc_types.h:1098
ERM_NONE
#define ERM_NONE
Definition fc_types.h:992
O_SHIELD
@ O_SHIELD
Definition fc_types.h:91
O_FOOD
@ O_FOOD
Definition fc_types.h:91
O_TRADE
@ O_TRADE
Definition fc_types.h:91
O_SCIENCE
@ O_SCIENCE
Definition fc_types.h:91
O_LUXURY
@ O_LUXURY
Definition fc_types.h:91
O_GOLD
@ O_GOLD
Definition fc_types.h:91
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
N_
#define N_(String)
Definition fcintl.h:69
ftc_client
const struct ft_color ftc_client
Definition featured_text.c:78
population_to_text
const char * population_to_text(int thousand_citizen)
Definition game.c:714
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:102
game.h
FC_STATIC_CANVAS_INIT
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:27
choice_dialog_start
GtkWidget * choice_dialog_start(GtkWindow *parent, const gchar *name, const gchar *text)
Definition choice_dialog.c:103
choice_dialog_end
void choice_dialog_end(GtkWidget *dshell)
Definition choice_dialog.c:194
choice_dialog_add
void choice_dialog_add(GtkWidget *dshell, const gchar *label, GCallback handler, gpointer data, bool meta, const gchar *tool_tip)
Definition choice_dialog.c:158
citizens_dialog_display
GtkWidget * citizens_dialog_display(const struct city *pcity)
Definition citizensinfo.c:381
citizens_dialog_refresh
void citizens_dialog_refresh(const struct city *pcity)
Definition citizensinfo.c:297
citizens_dialog_close
void citizens_dialog_close(const struct city *pcity)
Definition citizensinfo.c:363
unit_sentry_callback
static void unit_sentry_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2756
citydlg_response
citydlg_response
Definition citydlg.c:81
CDLGR_UNITS
@ CDLGR_UNITS
Definition citydlg.c:81
CDLGR_PREV
@ CDLGR_PREV
Definition citydlg.c:81
CDLGR_NEXT
@ CDLGR_NEXT
Definition citydlg.c:81
new_dialog_def_page
static int new_dialog_def_page
Definition citydlg.c:212
create_and_append_buildings_page
static void create_and_append_buildings_page(struct city_dialog *pdialog)
Definition citydlg.c:1193
unit_upgrade_callback
static void unit_upgrade_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2815
popup_workertask_dlg
static void popup_workertask_dlg(struct city *pcity, struct tile *ptile)
Definition citydlg.c:2927
city_dialog_update_citizens
static void city_dialog_update_citizens(struct city_dialog *pdialog)
Definition citydlg.c:1735
city_destroy_callback
static void city_destroy_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3346
city_dialog_update_title
static void city_dialog_update_title(struct city_dialog *pdialog)
Definition citydlg.c:1696
last_page
static int last_page
Definition citydlg.c:213
init_citydlg_dimensions
static void init_citydlg_dimensions(void)
Definition citydlg.c:324
create_and_append_worklist_page
static void create_and_append_worklist_page(struct city_dialog *pdialog)
Definition citydlg.c:1227
loc
struct tile * loc
Definition citydlg.c:220
canvas_exposed_cb
static gboolean canvas_exposed_cb(GtkWidget *w, cairo_t *cr, gpointer data)
Definition citydlg.c:396
CITY_MAP_MIN_SIZE_X
#define CITY_MAP_MIN_SIZE_X
Definition citydlg.c:127
real_city_dialog_popup
void real_city_dialog_popup(struct city *pcity)
Definition citydlg.c:558
misc_whichtab_callback
static void misc_whichtab_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3271
low_citydlg
static bool low_citydlg
Definition citydlg.c:223
city_dialog_is_open
bool city_dialog_is_open(struct city *pcity)
Definition citydlg.c:579
city_dialog_update_building
static void city_dialog_update_building(struct city_dialog *pdialog)
Definition citydlg.c:1926
citydlg_response_callback
static void citydlg_response_callback(GtkDialog *dlg, gint response, void *data)
Definition citydlg.c:2354
buy_callback_response
static void buy_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3061
present_unit_middle_callback
static gboolean present_unit_middle_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2599
real_city_dialog_refresh
void real_city_dialog_refresh(struct city *pcity)
Definition citydlg.c:481
unit_center_callback
static void unit_center_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2655
get_city_dialog
static struct city_dialog * get_city_dialog(struct city *pcity)
Definition citydlg.c:379
CITY_MAP_MIN_SIZE_Y
#define CITY_MAP_MIN_SIZE_Y
Definition citydlg.c:128
city_dialog_update_information
static void city_dialog_update_information(GtkWidget **info_ebox, GtkWidget **info_label, struct city_dialog *pdialog)
Definition citydlg.c:1798
create_citydlg_improvement_list
static GtkWidget * create_citydlg_improvement_list(struct city_dialog *pdialog, GtkWidget *vbox)
Definition citydlg.c:852
create_production_header
static void create_production_header(struct city_dialog *pdialog, GtkContainer *contain)
Definition citydlg.c:1160
workertask_dlg_destroy
static void workertask_dlg_destroy(GtkWidget *w, gpointer data)
Definition citydlg.c:2919
city_dialog_update_present_units
static void city_dialog_update_present_units(struct city_dialog *pdialog)
Definition citydlg.c:2211
CITYMAP_SCALE
#define CITYMAP_SCALE
Definition citydlg.c:75
keyboard_handler
static gboolean keyboard_handler(GtkWidget *widget, GdkEventKey *event, struct city_dialog *pdialog)
Definition citydlg.c:616
citizens_callback
static gboolean citizens_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2836
change_production_callback
static void change_production_callback(GtkComboBox *combo, struct city_dialog *pdialog)
Definition citydlg.c:3124
unit_load_callback
static void unit_load_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2730
set_cityopt_values
static void set_cityopt_values(struct city_dialog *pdialog)
Definition citydlg.c:3312
close_city_dialog
static void close_city_dialog(struct city_dialog *pdialog)
Definition citydlg.c:3401
show_info_popup
static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:653
create_and_append_overview_page
static void create_and_append_overview_page(struct city_dialog *pdialog)
Definition citydlg.c:911
create_and_append_happiness_page
static void create_and_append_happiness_page(struct city_dialog *pdialog)
Definition citydlg.c:1271
popdown_all_city_dialogs
void popdown_all_city_dialogs(void)
Definition citydlg.c:599
buy_callback
static void buy_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3074
dialog_list_iterate_end
#define dialog_list_iterate_end
Definition citydlg.c:92
impr_callback
static void impr_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition citydlg.c:3197
create_and_append_map_page
static void create_and_append_map_page(struct city_dialog *pdialog)
Definition citydlg.c:1099
city_dialog_map_create
static void city_dialog_map_create(struct city_dialog *pdialog, struct city_map_canvas *cmap_canvas)
Definition citydlg.c:415
refresh_unit_city_dialogs
void refresh_unit_city_dialogs(struct unit *punit)
Definition citydlg.c:538
reset_city_dialogs
void reset_city_dialogs(void)
Definition citydlg.c:357
show_info_button_release
static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:640
cityopt_callback
static void cityopt_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3279
city_dialog_map_recenter
static void city_dialog_map_recenter(GtkWidget *map_canvas_sw)
Definition citydlg.c:454
draw_map_canvas
static void draw_map_canvas(struct city_dialog *pdialog)
Definition citydlg.c:3049
is_showing_workertask_dialog
static bool is_showing_workertask_dialog
Definition citydlg.c:215
unit_node_vector_iterate_end
#define unit_node_vector_iterate_end
Definition citydlg.c:107
sell_callback
static void sell_callback(struct impr_type *pimprove, gpointer data)
Definition citydlg.c:3143
dialog_list_iterate
#define dialog_list_iterate(dialoglist, pdialog)
Definition citydlg.c:90
supported_unit_activate_close_callback
static void supported_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2682
city_dialog_update_prev_next
static void city_dialog_update_prev_next(void)
Definition citydlg.c:2318
create_and_append_settings_page
static void create_and_append_settings_page(struct city_dialog *pdialog)
Definition citydlg.c:1364
city_dialogs_have_been_initialised
static bool city_dialogs_have_been_initialised
Definition citydlg.c:210
close_callback
static void close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3338
dialog_list
static struct dialog_list * dialog_list
Definition citydlg.c:209
sell_callback_response
static void sell_callback_response(GtkWidget *w, gint response, gpointer data)
Definition citydlg.c:3182
create_citydlg_main_map
static void create_citydlg_main_map(struct city_dialog *pdialog, GtkWidget *container)
Definition citydlg.c:835
NUM_CITIZENS_SHOWN
#define NUM_CITIZENS_SHOWN
Definition citydlg.c:109
CITYMAP_HEIGHT
#define CITYMAP_HEIGHT
Definition citydlg.c:74
destroy_func
static void destroy_func(GtkWidget *w, gpointer data)
Definition citydlg.c:2407
unit_homecity_callback
static void unit_homecity_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2802
unit_fortify_callback
static void unit_fortify_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2769
supported_unit_middle_callback
static gboolean supported_unit_middle_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2627
present_unit_callback
static gboolean present_unit_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2479
owner
struct city * owner
Definition citydlg.c:219
create_city_info_table
static GtkWidget * create_city_info_table(struct city_dialog *pdialog, GtkWidget **info_ebox, GtkWidget **info_label)
Definition citydlg.c:737
create_city_dialog
static struct city_dialog * create_city_dialog(struct city *pcity)
Definition citydlg.c:1508
target_drag_data_received
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:1122
unit_disband_callback
static void unit_disband_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2782
unit_node_vector_iterate
#define unit_node_vector_iterate(list, elt)
Definition citydlg.c:105
INFO_LUXURY
@ INFO_LUXURY
Definition citydlg.c:119
INFO_STEAL
@ INFO_STEAL
Definition citydlg.c:121
INFO_CORRUPTION
@ INFO_CORRUPTION
Definition citydlg.c:120
NUM_INFO_FIELDS
@ NUM_INFO_FIELDS
Definition citydlg.c:122
INFO_ILLNESS
@ INFO_ILLNESS
Definition citydlg.c:121
INFO_WASTE
@ INFO_WASTE
Definition citydlg.c:120
INFO_SIZE
@ INFO_SIZE
Definition citydlg.c:118
INFO_GROWTH
@ INFO_GROWTH
Definition citydlg.c:119
INFO_SHIELD
@ INFO_SHIELD
Definition citydlg.c:118
INFO_CULTURE
@ INFO_CULTURE
Definition citydlg.c:120
INFO_GOLD
@ INFO_GOLD
Definition citydlg.c:118
INFO_SCIENCE
@ INFO_SCIENCE
Definition citydlg.c:119
INFO_POLLUTION
@ INFO_POLLUTION
Definition citydlg.c:120
INFO_TRADE
@ INFO_TRADE
Definition citydlg.c:118
INFO_AIRLIFT
@ INFO_AIRLIFT
Definition citydlg.c:121
INFO_GRANARY
@ INFO_GRANARY
Definition citydlg.c:119
INFO_FOOD
@ INFO_FOOD
Definition citydlg.c:118
rename_callback
static void rename_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3237
switch_city_callback
static void switch_city_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:3410
button_down_citymap
static gboolean button_down_citymap(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:3011
CITYMAP_WIDTH
#define CITYMAP_WIDTH
Definition citydlg.c:73
city_dialog_update_map
static void city_dialog_update_map(struct city_dialog *pdialog)
Definition citydlg.c:1904
unit_unload_callback
static void unit_unload_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2743
show_units_response
static void show_units_response(void *data)
Definition citydlg.c:2367
initialize_city_dialogs
static void initialize_city_dialogs(void)
Definition citydlg.c:333
canvas_height
static int canvas_height
Definition citydlg.c:211
canvas_width
static int canvas_width
Definition citydlg.c:211
TINYSCREEN_MAX_HEIGHT
#define TINYSCREEN_MAX_HEIGHT
Definition citydlg.c:77
city_dialog_update_supported_units
static void city_dialog_update_supported_units(struct city_dialog *pdialog)
Definition citydlg.c:2105
unit_activate_callback
static void unit_activate_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2668
present_unit_activate_close_callback
static void present_unit_activate_close_callback(GtkWidget *w, gpointer data)
Definition citydlg.c:2707
set_city_workertask
static void set_city_workertask(GtkWidget *w, gpointer data)
Definition citydlg.c:2863
rename_popup_callback
static void rename_popup_callback(gpointer data, gint response, const char *input)
Definition citydlg.c:3254
WORKLIST_PAGE
@ WORKLIST_PAGE
Definition citydlg.c:111
CMA_PAGE
@ CMA_PAGE
Definition citydlg.c:111
HAPPINESS_PAGE
@ HAPPINESS_PAGE
Definition citydlg.c:111
SETTINGS_PAGE
@ SETTINGS_PAGE
Definition citydlg.c:112
STICKY_PAGE
@ STICKY_PAGE
Definition citydlg.c:112
NUM_PAGES
@ NUM_PAGES
Definition citydlg.c:113
OVERVIEW_PAGE
@ OVERVIEW_PAGE
Definition citydlg.c:111
city_dialog_update_improvement_list
static void city_dialog_update_improvement_list(struct city_dialog *pdialog)
Definition citydlg.c:2048
create_and_append_cma_page
static void create_and_append_cma_page(struct city_dialog *pdialog)
Definition citydlg.c:1344
popdown_city_dialog
void popdown_city_dialog(struct city *pcity)
Definition citydlg.c:587
workertask_req
static struct @139 workertask_req
supported_unit_callback
static gboolean supported_unit_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition citydlg.c:2415
close_cma_dialog
void close_cma_dialog(struct city *pcity)
Definition cma_fe.c:104
create_cma_dialog
struct cma_dialog * create_cma_dialog(struct city *pcity, bool tiny)
Definition cma_fe.c:214
refresh_cma_dialog
void refresh_cma_dialog(struct city *pcity, enum cma_refresh refresh)
Definition cma_fe.c:472
REFRESH_ALL
@ REFRESH_ALL
Definition cma_fe.h:26
unit_select_dialog_popup
void unit_select_dialog_popup(struct tile *ptile)
Definition dialogs.c:382
popup_upgrade_dialog
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1444
popup_disband_dialog
void popup_disband_dialog(struct unit_list *punits)
Definition dialogs.c:1482
toplevel
GtkWidget * toplevel
Definition gui_main.c:124
map_canvas
GtkWidget * map_canvas
Definition gui_main.c:106
screen_height
int screen_height(void)
Definition gui_main.c:2375
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
intl_slist
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:105
close_happiness_dialog
void close_happiness_dialog(struct city *pcity)
Definition happiness.c:330
refresh_happiness_dialog
void refresh_happiness_dialog(struct city *pcity)
Definition happiness.c:317
get_top_happiness_display
GtkWidget * get_top_happiness_display(struct city *pcity, bool low_dlg, GtkWidget *win)
Definition happiness.c:356
popup_help_dialog_typed
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Definition helpdlg.c:195
input_dialog_create
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
put_unit_image_city_overlays
void put_unit_image_city_overlays(struct unit *punit, GtkImage *p, int height, int *upkeep_cost, int happy_cost)
Definition mapview.c:503
put_unit_image
void put_unit_image(struct unit *punit, GtkImage *p, int height)
Definition mapview.c:478
shell
static struct gui_dialog * shell
Definition messagedlg.c:39
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
request_transport
bool request_transport(struct unit *cargo, struct tile *ptile)
Definition transportdlg.c:82
refresh_worklist
void refresh_worklist(GtkWidget *editor)
Definition wldlg.c:1329
add_worklist_dnd_target
void add_worklist_dnd_target(GtkWidget *w)
Definition wldlg.c:337
reset_city_worklist
void reset_city_worklist(GtkWidget *editor, struct city *pcity)
Definition wldlg.c:1281
create_worklist
GtkWidget * create_worklist(void)
Definition wldlg.c:1054
icon_label_button_new
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
choice_dialog.h
citizensinfo.h
gui_stuff.h
happiness.h
inputdlg.h
cma_fe.h
citydlg.h
cityrep.h
colors.h
dialogs.h
graphics.h
gui_main.h
helpdlg.h
mapview.h
repodlgs.h
wldlg.h
HELP_IMPROVEMENT
@ HELP_IMPROVEMENT
Definition helpdlg_g.h:20
HELP_WONDER
@ HELP_WONDER
Definition helpdlg_g.h:21
impr_sell_gold
int impr_sell_gold(const struct impr_type *pimprove)
Definition improvement.c:332
test_player_sell_building_now
enum test_result test_player_sell_building_now(struct player *pplayer, struct city *pcity, const struct impr_type *pimprove)
Definition improvement.c:1083
is_improvement_redundant
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
Definition improvement.c:636
improvement_number
Impr_type_id improvement_number(const struct impr_type *pimprove)
Definition improvement.c:182
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:767
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:241
is_small_wonder
bool is_small_wonder(const struct impr_type *pimprove)
Definition improvement.c:775
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
map.h
center_tile_mapcanvas
void center_tile_mapcanvas(const struct tile *ptile)
Definition mapview_common.c:1222
can_slide
bool can_slide
Definition mapview_common.c:75
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
unit_can_load
bool unit_can_load(const struct unit *punit)
Definition movement.c:841
movement.h
options.h
GUI_GTK3_22_CITYDLG_MAX_XSIZE
#define GUI_GTK3_22_CITYDLG_MAX_XSIZE
Definition options.h:597
GUI_GTK3_22_CITYDLG_MIN_XSIZE
#define GUI_GTK3_22_CITYDLG_MIN_XSIZE
Definition options.h:596
packets.h
send_packet_worker_task
int send_packet_worker_task(struct connection *pc, const struct packet_worker_task *packet)
Definition packets_gen.c:32553
dsend_packet_city_options_req
int dsend_packet_city_options_req(struct connection *pc, int city_id16, int city_id32, bv_city_options options)
Definition packets_gen.c:29671
len
int len
Definition packhand.c:125
player_unit_by_number
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1205
player_city_by_number
struct city * player_city_by_number(const struct player *pplayer, int city_id)
Definition player.c:1179
player.h
economy_report_dialog_update
void economy_report_dialog_update(void)
Definition update_queue.c:682
shared.h
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
speclist.h
specvec.h
size
size_t size
Definition specvec.h:72
canvas
Definition canvas.h:21
canvas::surface
cairo_surface_t * surface
Definition canvas.h:22
city_dialog
Definition citydlg.c:136
city_dialog::prev_command
GtkWidget * prev_command
Definition citydlg.c:202
city_dialog::name_label
GtkWidget * name_label
Definition citydlg.c:140
city_dialog::rename_shell
GtkWidget * rename_shell
Definition citydlg.c:199
city_dialog::info_ebox
GtkWidget * info_ebox[NUM_INFO_FIELDS]
Definition citydlg.c:165
city_dialog::rename_command
GtkWidget * rename_command
Definition citydlg.c:190
city_dialog::production_bar
GtkWidget * production_bar
Definition citydlg.c:151
city_dialog::supported_units_frame
GtkWidget * supported_units_frame
Definition citydlg.c:156
city_dialog::popup_menu
GtkWidget * popup_menu
Definition citydlg.c:144
city_dialog::sell_shell
GtkWidget * sell_shell
Definition citydlg.c:197
city_dialog::production_label
GtkWidget * production_label
Definition citydlg.c:172
city_dialog::cwidth
int cwidth
Definition citydlg.c:206
city_dialog::misc
struct city_dialog::@143 misc
city_dialog::widget
GtkWidget * widget
Definition citydlg.c:181
city_dialog::supported_unit_table
GtkWidget * supported_unit_table
Definition citydlg.c:157
city_dialog::disband_on_settler
GtkWidget * disband_on_settler
Definition citydlg.c:192
city_dialog::page
enum city_dialog::@211 page
city_dialog::map_canvas
struct city_map_canvas map_canvas
Definition citydlg.c:149
city_dialog::improvement_list
GtkWidget * improvement_list
Definition citydlg.c:154
city_dialog::buy_command
GtkWidget * buy_command
Definition citydlg.c:153
city_dialog::block_signal
short block_signal
Definition citydlg.c:194
city_dialog::whichtab_radio
GtkWidget * whichtab_radio[NUM_PAGES]
Definition citydlg.c:193
city_dialog::supported_units
struct unit_node_vector supported_units
Definition citydlg.c:162
city_dialog::map_canvas_store_unscaled
cairo_surface_t * map_canvas_store_unscaled
Definition citydlg.c:141
city_dialog::pcity
struct city * pcity
Definition citydlg.c:137
city_dialog::present_units
struct unit_node_vector present_units
Definition citydlg.c:163
city_dialog::happiness
struct city_dialog::@142 happiness
city_dialog::view
city_map * view
Definition citydlg.h:450
city_dialog::production
struct city_dialog::@141 production
city_dialog::citizens
GtkWidget * citizens
Definition citydlg.c:184
city_dialog::show_units_command
GtkWidget * show_units_command
Definition citydlg.c:201
city_dialog::sell_id
Impr_type_id sell_id
Definition citydlg.c:204
city_dialog::production_combo
GtkWidget * production_combo
Definition citydlg.c:152
city_dialog::overview
struct city_dialog::@140 overview
city_dialog::cma_editor
struct cma_dialog * cma_editor
Definition citydlg.c:187
city_dialog::citizen_surface
cairo_surface_t * citizen_surface
Definition citydlg.c:146
city_dialog::shell
GtkWidget * shell
Definition citydlg.c:139
city_dialog::citizen_images
GtkWidget * citizen_images
Definition citydlg.c:145
city_dialog::worklist
GtkWidget * worklist
Definition citydlg.c:175
city_dialog::present_units_frame
GtkWidget * present_units_frame
Definition citydlg.c:159
city_dialog::info_label
GtkWidget * info_label[NUM_INFO_FIELDS]
Definition citydlg.c:166
city_dialog::new_citizens_radio
GtkWidget * new_citizens_radio[3]
Definition citydlg.c:191
city_dialog::change_production_store
GtkListStore * change_production_store
Definition citydlg.c:168
city_dialog::present_unit_table
GtkWidget * present_unit_table
Definition citydlg.c:160
city_dialog::notebook
GtkWidget * notebook
Definition citydlg.c:142
city_dialog::next_command
GtkWidget * next_command
Definition citydlg.c:202
city_dialog::change_selection
GtkTreeSelection * change_selection
Definition citydlg.c:198
city_map_canvas
Definition citydlg.c:130
city_map_canvas::darea
GtkWidget * darea
Definition citydlg.c:133
city_map_canvas::sw
GtkWidget * sw
Definition citydlg.c:131
city_map_canvas::ebox
GtkWidget * ebox
Definition citydlg.c:132
city
Definition city.h:309
city::task_reqs
struct worker_task_list * task_reqs
Definition city.h:395
city::surplus
int surplus[O_LAST]
Definition city.h:343
city::food_stock
int food_stock
Definition city.h:354
city::pollution
int pollution
Definition city.h:356
city::id
int id
Definition city.h:315
city::waste
int waste[O_LAST]
Definition city.h:344
city::info_units_present
struct unit_list * info_units_present
Definition city.h:457
city::owner
struct player * owner
Definition city.h:312
city::info_units_supported
struct unit_list * info_units_supported
Definition city.h:456
city::worklist
struct worklist worklist
Definition city.h:387
city::steal
int steal
Definition city.h:397
city::size
citizens size
Definition city.h:320
city::illness
int illness
Definition city.h:417
city::culture
int culture
Definition city.h:448
city::buy_cost
int buy_cost
Definition city.h:449
city::tile
struct tile * tile
Definition city.h:311
city::shield_stock
int shield_stock
Definition city.h:355
city::prod
int prod[O_LAST]
Definition city.h:346
city::units_supported
struct unit_list * units_supported
Definition city.h:391
city::client
struct city::@17::@20 client
civ_game::info
struct packet_game_info info
Definition game.h:89
civclient::conn
struct connection conn
Definition client_main.h:96
cma_dialog
Definition cma_fe.h:31
cma_dialog::shell
GtkWidget * shell
Definition cma_fe.h:33
cma_dialog::pcity
struct city * pcity
Definition cma_fe.h:32
connection::playing
struct player * playing
Definition connection.h:156
container
Definition widget.h:102
extra_type
Definition extras.h:85
impr_type
Definition improvement.h:68
item
Definition climisc.h:80
item::item
struct universal item
Definition climisc.h:81
item::descr
char descr[MAX_LEN_NAME+40]
Definition climisc.h:82
packet_game_info::citizen_nationality
bool citizen_nationality
Definition packets_gen.h:143
packet_game_info::illness_on
bool illness_on
Definition packets_gen.h:181
packet_worker_task
Definition packets_gen.h:506
packet_worker_task::tile_id
int tile_id
Definition packets_gen.h:509
packet_worker_task::city_id16
int city_id16
Definition packets_gen.h:507
packet_worker_task::city_id32
int city_id32
Definition packets_gen.h:508
packet_worker_task::activity
enum unit_activity activity
Definition packets_gen.h:510
packet_worker_task::want
int want
Definition packets_gen.h:512
packet_worker_task::tgt
int tgt
Definition packets_gen.h:511
player
Definition player.h:249
player::cities
struct city_list * cities
Definition player.h:281
sprite
Definition sprite.h:22
terrain
Definition terrain.h:176
terrain::cultivate_result
struct terrain * cultivate_result
Definition terrain.h:203
terrain::plant_result
struct terrain * plant_result
Definition terrain.h:206
terrain::transform_result
struct terrain * transform_result
Definition terrain.h:217
tile
Definition tile.h:49
tile::index
int index
Definition tile.h:50
tile::units
struct unit_list * units
Definition tile.h:57
tileset
Definition tilespec.c:459
unit_node
Definition citydlg.c:94
unit_node::height
int height
Definition citydlg.c:97
unit_node::cmd
GtkWidget * cmd
Definition citydlg.c:95
unit_node::pix
GtkWidget * pix
Definition citydlg.c:96
unit
Definition unit.h:138
unit::upkeep
int upkeep[O_LAST]
Definition unit.h:148
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::id
int id
Definition unit.h:145
unit::homecity
int homecity
Definition unit.h:146
universal
Definition fc_types.h:756
universal::kind
enum universals_n kind
Definition fc_types.h:758
universal::value
universals_u value
Definition fc_types.h:757
view
Definition mapview_common.h:36
widget
Definition widget.h:112
worker_task
Definition workertask.h:21
worker_task::ptile
struct tile * ptile
Definition workertask.h:22
worklist
Definition worklist.h:28
world::map
struct civ_map map
Definition world_object.h:38
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
unit_description
const char * unit_description(struct unit *punit)
Definition text.c:508
text.h
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
get_building_sprite
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:6498
tileset_small_sprite_width
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:864
get_unittype_sprite
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing)
Definition tilespec.c:6520
tileset_full_tile_height
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:752
tileset_small_sprite_height
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:900
get_icon_sprite
struct sprite * get_icon_sprite(const struct tileset *t, enum icon_type icon)
Definition tilespec.c:6678
tileset_unit_with_upkeep_height
int tileset_unit_with_upkeep_height(const struct tileset *t)
Definition tilespec.c:822
get_citizen_sprite
struct sprite * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Definition tilespec.c:6441
tilespec.h
ICON_CITYDLG
@ ICON_CITYDLG
Definition tilespec.h:311
universals_u::utype
const struct unit_type * utype
Definition fc_types.h:604
universals_u::building
const struct impr_type * building
Definition fc_types.h:598
can_unit_change_homecity_to
bool can_unit_change_homecity_to(const struct unit *punit, const struct city *pcity)
Definition unit.c:445
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2421
unit_can_do_action
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:330
can_unit_unload
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:767
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
can_upgrade_unittype
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1755
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
info_label
static SDL_Surface * info_label
Definition widget.c:57
worklist_is_empty
bool worklist_is_empty(const struct worklist *pwl)
Definition worklist.c:66