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

Freeciv-3.3

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