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