Freeciv-3.1
Loading...
Searching...
No Matches
citizensinfo.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/* common */
26#include "citizens.h"
27#include "city.h"
28#include "player.h"
29
30/* client/gui-gtk-4.0 */
31#include "gui_stuff.h"
32#include "plrdlg.h"
33
34#include "citizensinfo.h"
35
36
37static struct citizens_dialog *citizens_dialog_get(const struct city *pcity);
38static struct citizens_dialog
39 *citizens_dialog_create(const struct city *pcity);
40static GtkTreeStore *citizens_dialog_store_new(void);
42static void citizens_dialog_row(GtkTreeStore *store, GtkTreeIter *it,
43 const struct city *pcity,
44 const struct player_slot *pslot);
45
46static const char *col_nation(const struct city *pcity,
47 const struct player_slot *pslot);
48static const char *col_citizens(const struct city *pcity,
49 const struct player_slot *pslot);
50
51/*****************************************************************************
52 The layout of the citizens display.
53*****************************************************************************/
54static struct citizens_column {
55 bool show;
57 const char *title;
58 const char *(*func)(const struct city *, const struct player_slot *);
59 /* if type = COL_*TEXT */
60 const char *tagname; /* for save_options */
61} citizens_cols[] = {
62 {TRUE, COL_RIGHT_TEXT, N_("#"), col_citizens, "citizens"},
63 {TRUE, COL_FLAG, N_("Flag"), NULL, "flag"},
64 {TRUE, COL_TEXT, N_("Nation"), col_nation, "nation"}
65};
67#define CITIZENS_DLG_COL_STYLE (0 + num_citizens_cols)
68#define CITIZENS_DLG_COL_WEIGHT (1 + num_citizens_cols)
69#define CITIZENS_DLG_COL_ID (2 + num_citizens_cols)
70
71/*****************************************************************************
72 The citizens dialog.
73*****************************************************************************/
74struct citizens_dialog {
75 const struct city *pcity;
76 GtkWidget *shell;
77 GtkTreeStore *store;
78 GtkWidget *list;
79 GtkTreeModel *sort;
80};
81
82#define SPECLIST_TAG dialog
83#define SPECLIST_TYPE struct citizens_dialog
84#include "speclist.h"
85
86#define dialog_list_iterate(dialoglist, pdialog) \
87 TYPED_LIST_ITERATE(struct citizens_dialog, dialoglist, pdialog)
88#define dialog_list_iterate_end LIST_ITERATE_END
89
90static struct dialog_list *dialog_list;
91
92/*************************************************************************/
95static const char *col_nation(const struct city *pcity,
96 const struct player_slot *pslot)
97{
99}
100
101/*************************************************************************/
104static const char *col_citizens(const struct city *pcity,
105 const struct player_slot *pslot)
106{
107 citizens nationality = citizens_nation_get(pcity, pslot);
108
109 if (nationality == 0) {
110 return "-";
111 } else {
112 static char buf[8];
113
114 fc_snprintf(buf, sizeof(buf), "%d", nationality);
115
116 return buf;
117 }
118}
119
120/*************************************************************************/
125static GtkTreeStore *citizens_dialog_store_new(void)
126{
127 GtkTreeStore *store;
128 GType model_types[num_citizens_cols + 3];
129 int i;
130
131 for (i = 0; i < num_citizens_cols; i++) {
132 switch (citizens_cols[i].type) {
133 case COL_FLAG:
134 model_types[i] = GDK_TYPE_PIXBUF;
135 break;
136 case COL_COLOR:
137 model_types[i] = GDK_TYPE_PIXBUF;
138 break;
139 case COL_BOOLEAN:
140 model_types[i] = G_TYPE_BOOLEAN;
141 break;
142 case COL_TEXT:
143 case COL_RIGHT_TEXT:
144 model_types[i] = G_TYPE_STRING;
145 break;
146 }
147 }
148 /* special (invisible rows) - Text style, weight and player id */
149 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_STYLE. */
150 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_WEIGHT. */
151 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_ID. */
152
153 store = gtk_tree_store_newv(i, model_types);
154
155 return store;
156}
157
158/*************************************************************************/
162{
163 return 0;
164}
165
166/*************************************************************************/
170{
171 GtkWidget *frame, *sw;
172 struct citizens_dialog *pdialog = fc_malloc(sizeof(struct citizens_dialog));
173 int i;
174
175 pdialog->pcity = pcity;
176 pdialog->store = citizens_dialog_store_new();
177 pdialog->sort
178 = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(pdialog->store));
179 g_object_unref(pdialog->store);
180
181 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(pdialog->sort),
183 GTK_SORT_DESCENDING);
184
185 pdialog->list
186 = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pdialog->sort));
187 gtk_widget_set_halign(pdialog->list, GTK_ALIGN_CENTER);
188 g_object_unref(pdialog->sort);
189
190 for (i = 0; i < num_citizens_cols; i++) {
191 struct citizens_column *pcol;
192 GtkCellRenderer *renderer;
193 GtkTreeViewColumn *col;
194
195 pcol = &citizens_cols[i];
196 col = NULL;
197
198 switch (pcol->type) {
199 case COL_FLAG:
200 renderer = gtk_cell_renderer_pixbuf_new();
201 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
202 "pixbuf", i, NULL);
203 break;
204 case COL_TEXT:
205 renderer = gtk_cell_renderer_text_new();
206 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
207
208 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
209 "text", i,
210 "style", CITIZENS_DLG_COL_STYLE,
211 "weight", CITIZENS_DLG_COL_WEIGHT,
212 NULL);
213 gtk_tree_view_column_set_sort_column_id(col, i);
214 break;
215 case COL_RIGHT_TEXT:
216 renderer = gtk_cell_renderer_text_new();
217 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
218
219 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
220 "text", i,
221 "style", CITIZENS_DLG_COL_STYLE,
222 "weight", CITIZENS_DLG_COL_WEIGHT,
223 NULL);
224 gtk_tree_view_column_set_sort_column_id(col, i);
225 g_object_set(renderer, "xalign", 1.0, NULL);
226 gtk_tree_view_column_set_alignment(col, 1.0);
227 break;
228 case COL_COLOR:
229 case COL_BOOLEAN:
230 /* These are not used. */
231 fc_assert(pcol->type != COL_COLOR && pcol->type != COL_BOOLEAN);
232 continue;
233 }
234
235 if (col) {
236 gtk_tree_view_append_column(GTK_TREE_VIEW(pdialog->list), col);
237 }
238 }
239
240 gtk_widget_set_hexpand(GTK_WIDGET(pdialog->list), TRUE);
241 gtk_widget_set_vexpand(GTK_WIDGET(pdialog->list), TRUE);
242
243 sw = gtk_scrolled_window_new();
244 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
245 GTK_POLICY_AUTOMATIC,
246 GTK_POLICY_AUTOMATIC);
247 gtk_scrolled_window_set_has_frame(GTK_SCROLLED_WINDOW(sw), FALSE);
248 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), pdialog->list);
249
250 frame = gtk_frame_new(_("Citizens"));
251 gtk_frame_set_child(GTK_FRAME(frame), sw);
252
253 pdialog->shell = frame;
254
255 dialog_list_prepend(dialog_list, pdialog);
256
258
259 return pdialog;
260}
261
262/*************************************************************************/
266{
267 dialog_list = dialog_list_new();
268}
269
270/*************************************************************************/
274{
275 dialog_list_destroy(dialog_list);
276}
277
278/*************************************************************************/
281static struct citizens_dialog *citizens_dialog_get(const struct city *pcity)
282{
284 if (pdialog->pcity == pcity) {
285 return pdialog;
286 }
288
289 return NULL;
290}
291
292/*************************************************************************/
296{
297 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
298
299 if (pdialog == NULL) {
300 return;
301 }
302
303 gtk_tree_store_clear(pdialog->store);
304 citizens_iterate(pcity, pslot, nationality) {
305 GtkTreeIter iter;
306
307 gtk_tree_store_append(pdialog->store, &iter, NULL);
308 citizens_dialog_row(pdialog->store, &iter, pcity, pslot);
310}
311
312/*************************************************************************/
315static void citizens_dialog_row(GtkTreeStore *store, GtkTreeIter *it,
316 const struct city *pcity,
317 const struct player_slot *pslot)
318{
319 GdkPixbuf *pixbuf;
320 int style = PANGO_STYLE_NORMAL, weight = PANGO_WEIGHT_NORMAL;
321 int k;
322
323 for (k = 0; k < num_citizens_cols; k++) {
324 struct citizens_column *pcol = &citizens_cols[k];
325 switch (pcol->type) {
326 case COL_TEXT:
327 case COL_RIGHT_TEXT:
328 gtk_tree_store_set(store, it, k, pcol->func(pcity, pslot), -1);
329 break;
330 case COL_FLAG:
332 if (pixbuf != NULL) {
333 gtk_tree_store_set(store, it, k, pixbuf, -1);
334 g_object_unref(pixbuf);
335 }
336 break;
337 case COL_COLOR:
338 case COL_BOOLEAN:
339 /* These are not used. */
340 fc_assert(pcol->type != COL_COLOR && pcol->type != COL_BOOLEAN);
341 continue;
342 break;
343 }
344 }
345
346 if (city_owner(pcity)->slot == pslot) {
347 weight = PANGO_WEIGHT_BOLD;
348 style = PANGO_STYLE_NORMAL;
349 }
350
351 gtk_tree_store_set(store, it,
355 -1);
356}
357
358/*************************************************************************/
361void citizens_dialog_close(const struct city *pcity)
362{
363 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
364
365 if (pdialog == NULL) {
366 return;
367 }
368
369 gtk_widget_hide(pdialog->shell);
370
371 dialog_list_remove(dialog_list, pdialog);
372
373 gtk_box_remove(GTK_BOX(gtk_widget_get_parent(pdialog->shell)),
374 pdialog->shell);
375 free(pdialog);
376}
377
378/*************************************************************************/
381GtkWidget *citizens_dialog_display(const struct city *pcity)
382{
383 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
384
385 if (!pdialog) {
386 pdialog = citizens_dialog_create(pcity);
387 }
388
389 gtk_widget_show(pdialog->shell);
391
392 return pdialog->shell;
393}
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
#define city_owner(_pcity_)
Definition city.h:543
unsigned char citizens
Definition fc_types.h:358
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
#define CITIZENS_DLG_COL_STYLE
void citizens_dialog_init(void)
static const char * col_citizens(const struct city *pcity, const struct player_slot *pslot)
GtkWidget * citizens_dialog_display(const struct city *pcity)
static struct citizens_column citizens_cols[]
void citizens_dialog_refresh(const struct city *pcity)
#define dialog_list_iterate_end
static struct citizens_dialog * citizens_dialog_create(const struct city *pcity)
#define CITIZENS_DLG_COL_ID
static const int num_citizens_cols
#define CITIZENS_DLG_COL_WEIGHT
#define dialog_list_iterate(dialoglist, pdialog)
void citizens_dialog_close(const struct city *pcity)
static struct dialog_list * dialog_list
static GtkTreeStore * citizens_dialog_store_new(void)
static int citizens_dialog_default_sort_column(void)
static const char * col_nation(const struct city *pcity, const struct player_slot *pslot)
static struct citizens_dialog * citizens_dialog_get(const struct city *pcity)
static void citizens_dialog_row(GtkTreeStore *store, GtkTreeIter *it, const struct city *pcity, const struct player_slot *pslot)
void citizens_dialog_done(void)
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:609
GType type
Definition repodlgs.c:1312
@ COL_TEXT
Definition unitselect.c:50
#define fc_assert(condition)
Definition log.h:176
#define fc_malloc(sz)
Definition mem.h:34
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
int player_slot_index(const struct player_slot *pslot)
Definition player.c:419
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:430
player_dlg_column_type
@ COL_BOOLEAN
@ COL_FLAG
@ COL_RIGHT_TEXT
@ COL_COLOR
#define ARRAY_SIZE(x)
Definition shared.h:85
const char * tagname
const char *(* func)(const struct city *, const struct player_slot *)
enum player_dlg_column_type type
const char * title
GtkTreeStore * store
const struct city * pcity
GtkTreeModel * sort
GtkWidget * list
GtkWidget * shell
Definition city.h:309
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47