1 /* Pioneers - Implementation of the excellent Settlers of Catan board game.
2 * Go buy a copy.
3 *
4 * Copyright (C) 1999 Dave Cole
5 * Copyright (C) 2003 Bas Wijnen <shevek@fmf.nl>
6 * Copyright (C) 2004-2005 Roland Clobus <rclobus@bigfoot.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "config.h"
24 #include <math.h>
25 #include <ctype.h>
26 #include <assert.h>
27
28 #include "aboutbox.h"
29 #include "frontend.h"
30 #include "cards.h"
31 #include "cost.h"
32 #include "log.h"
33 #include "common_gtk.h"
34 #include "histogram.h"
35 #include "theme.h"
36 #include "config-gnome.h"
37 #include "audio.h"
38 #include "notification.h"
39
40 static GtkWidget *preferences_dlg;
41 GtkWidget *app_window; /* main application window */
42
43 #define MAP_WIDTH 350 /* default map width */
44 #define MAP_HEIGHT 200 /* default map height */
45
46 #define PIONEERS_ICON_FILE "pioneers.png"
47
48 /* Callback functions from the resource file */
49 G_MODULE_EXPORT void game_quit_cb(GObject * gobject, gpointer user_data);
50 G_MODULE_EXPORT void game_legend_cb(GObject * gobject, gpointer user_data);
51 G_MODULE_EXPORT void game_histogram_cb(GObject * gobject,
52 gpointer user_data);
53 G_MODULE_EXPORT void game_settings_cb(GObject * gobject,
54 gpointer user_data);
55 G_MODULE_EXPORT void show_admin_interface_cb(GObject * gobject,
56 gpointer user_data);
57 G_MODULE_EXPORT void zoom_normal_cb(GObject * gobject, gpointer user_data);
58 G_MODULE_EXPORT void zoom_center_map_cb(GObject * gobject,
59 gpointer user_data);
60 G_MODULE_EXPORT void toggle_full_screen_cb(GObject * gobject,
61 gpointer user_data);
62 G_MODULE_EXPORT void showhide_toolbar_cb(GObject * gobject,
63 gpointer user_data);
64 G_MODULE_EXPORT void preferences_cb(GObject * gobject, gpointer user_data);
65 G_MODULE_EXPORT void help_about_cb(GObject * gobject, gpointer user_data);
66 #ifdef HAVE_HELP
67 G_MODULE_EXPORT void help_manual_cb(GObject * gobject, gpointer user_data);
68 #endif
69
70 static GuiMap *gmap; /* handle to map drawing code */
71
72 enum {
73 MAP_PAGE, /* the map */
74 TRADE_PAGE, /* trading interface */
75 QUOTE_PAGE, /* submit quotes page */
76 LEGEND_PAGE, /* legend */
77 SPLASH_PAGE /* splash screen */
78 };
79
80 static GtkWidget *map_notebook; /* map area panel */
81 static GtkWidget *trade_page; /* trade page in map area */
82 static GtkWidget *quote_page; /* quote page in map area */
83 static GtkWidget *legend_page; /* legend page in map area */
84 static GtkWidget *splash_page; /* splash page in map area */
85
86 static GtkWidget *develop_notebook; /* development card area panel */
87
88 static GtkWidget *messages_txt; /* messages text widget */
89 static GtkWidget *prompt_lbl; /* big prompt messages */
90
91 static GtkWidget *app_bar;
92 static GtkWidget *net_status;
93 static GtkWidget *vp_target_status;
94
95 static GtkWidget *main_paned; /* Horizontal for 16:9, Vertical for 4:3 mode */
96 static GtkWidget *chat_panel = NULL; /* Panel for chat, placed below or to the right */
97
98 static GtkBuilder *builder = NULL; /* The manager of the GUI */
99 static GActionGroup *action_group = NULL; /* Global action group */
100
101 static gboolean toolbar_show_accelerators = TRUE;
102 static gboolean color_messages_enabled = TRUE;
103 static gboolean legend_page_enabled = TRUE;
104 static gboolean charity_enabled = FALSE;
105 static TAutomaticRoll automatic_roll = ROLL_MANUALLY;
106
107 static GList *rules_callback_list = NULL;
108
109 static void gui_set_toolbar_visible(gboolean visible);
110 static void gui_toolbar_show_accelerators(gboolean show_accelerators);
111
redirect_gui_event_cb(G_GNUC_UNUSED GSimpleAction * action,G_GNUC_UNUSED GVariant * parameter,gpointer user_data)112 static void redirect_gui_event_cb(G_GNUC_UNUSED GSimpleAction * action,
113 G_GNUC_UNUSED GVariant * parameter,
114 gpointer user_data)
115 {
116 route_gui_event(g_variant_get_int32(user_data));
117 }
118
game_leave_cb(G_GNUC_UNUSED GSimpleAction * action,G_GNUC_UNUSED GVariant * parameter,G_GNUC_UNUSED gpointer user_data)119 static void game_leave_cb(G_GNUC_UNUSED GSimpleAction * action,
120 G_GNUC_UNUSED GVariant * parameter,
121 G_GNUC_UNUSED gpointer user_data)
122 {
123 frontend_quote_end();
124 route_gui_event(GUI_DISCONNECT);
125 }
126
game_quit_cb(G_GNUC_UNUSED GObject * gobject,G_GNUC_UNUSED gpointer user_data)127 void game_quit_cb(G_GNUC_UNUSED GObject * gobject,
128 G_GNUC_UNUSED gpointer user_data)
129 {
130 guimap_delete(gmap);
131 route_gui_event(GUI_QUIT);
132 }
133
show_admin_interface_cb(G_GNUC_UNUSED GObject * gobject,G_GNUC_UNUSED gpointer user_data)134 void show_admin_interface_cb(G_GNUC_UNUSED GObject * gobject,
135 G_GNUC_UNUSED gpointer user_data)
136 {
137 #ifdef ADMIN_GTK
138 show_admin_interface();
139 #endif
140 }
141
toggle_full_screen_cb(GObject * gobject,gpointer user_data)142 void toggle_full_screen_cb(GObject * gobject, gpointer user_data)
143 {
144 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gobject))) {
145 gtk_window_fullscreen(GTK_WINDOW(user_data));
146 } else {
147 gtk_window_unfullscreen(GTK_WINDOW(user_data));
148 }
149 }
150
zoom_normal_cb(G_GNUC_UNUSED GObject * gobject,G_GNUC_UNUSED gpointer user_data)151 void zoom_normal_cb(G_GNUC_UNUSED GObject * gobject,
152 G_GNUC_UNUSED gpointer user_data)
153 {
154 guimap_zoom_normal(gmap);
155 }
156
zoom_center_map_cb(G_GNUC_UNUSED GObject * gobject,G_GNUC_UNUSED gpointer user_data)157 void zoom_center_map_cb(G_GNUC_UNUSED GObject * gobject,
158 G_GNUC_UNUSED gpointer user_data)
159 {
160 guimap_zoom_center_map(gmap);
161 }
162
gui_get_dialog_button(GtkDialog * dlg,gint button)163 GtkWidget *gui_get_dialog_button(GtkDialog * dlg, gint button)
164 {
165 GList *list;
166
167 g_return_val_if_fail(dlg != NULL, NULL);
168 g_assert(gtk_dialog_get_action_area(dlg) != NULL);
169
170 list =
171 gtk_container_get_children(GTK_CONTAINER
172 (gtk_dialog_get_action_area(dlg)));
173 list = g_list_nth(list, button);
174 if (list != NULL) {
175 g_assert(list->data != NULL);
176 return GTK_WIDGET(list->data);
177 }
178 return NULL;
179 }
180
gui_reset(void)181 void gui_reset(void)
182 {
183 guimap_reset(gmap);
184 }
185
gui_set_instructions(const gchar * text)186 void gui_set_instructions(const gchar * text)
187 {
188 gtk_statusbar_push(GTK_STATUSBAR(app_bar), 0, text);
189 }
190
gui_set_vp_target_value(gint vp)191 void gui_set_vp_target_value(gint vp)
192 {
193 gchar *vp_text;
194
195 /* Victory points target in statusbar */
196 vp_text = g_strdup_printf(_("Points needed to win: %i"), vp);
197
198 gtk_label_set_text(GTK_LABEL(vp_target_status), vp_text);
199 g_free(vp_text);
200 }
201
gui_set_net_status(const gchar * text)202 void gui_set_net_status(const gchar * text)
203 {
204 gtk_label_set_text(GTK_LABEL(net_status), text);
205 }
206
gui_cursor_none(void)207 void gui_cursor_none(void)
208 {
209 MapElement dummyElement;
210 dummyElement.pointer = NULL;
211 guimap_cursor_set(gmap, NO_CURSOR, -1, NULL, NULL, NULL,
212 &dummyElement, FALSE);
213 }
214
gui_cursor_set(CursorType type,CheckFunc check_func,SelectFunc select_func,CancelFunc cancel_func,const MapElement * user_data)215 void gui_cursor_set(CursorType type,
216 CheckFunc check_func, SelectFunc select_func,
217 CancelFunc cancel_func, const MapElement * user_data)
218 {
219 guimap_cursor_set(gmap, type, my_player_num(),
220 check_func, select_func, cancel_func, user_data,
221 FALSE);
222 }
223
gui_draw_hex(const Hex * hex)224 void gui_draw_hex(const Hex * hex)
225 {
226 if (gmap->surface != NULL)
227 guimap_draw_hex(gmap, hex);
228 }
229
gui_draw_edge(const Edge * edge)230 void gui_draw_edge(const Edge * edge)
231 {
232 if (gmap->surface != NULL)
233 guimap_draw_edge(gmap, edge);
234 }
235
gui_draw_node(const Node * node)236 void gui_draw_node(const Node * node)
237 {
238 if (gmap->surface != NULL)
239 guimap_draw_node(gmap, node);
240 }
241
gui_highlight_chits(gint roll)242 void gui_highlight_chits(gint roll)
243 {
244 guimap_highlight_chits(gmap, roll);
245 }
246
button_press_map_cb(GtkWidget * area,GdkEventButton * event,G_GNUC_UNUSED gpointer user_data)247 static gint button_press_map_cb(GtkWidget * area, GdkEventButton * event,
248 G_GNUC_UNUSED gpointer user_data)
249 {
250 if (gtk_widget_get_window(area) == NULL || gmap->map == NULL)
251 return FALSE;
252
253 if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
254 guimap_cursor_select(gmap);
255 return TRUE;
256 }
257 return FALSE;
258 }
259
build_map_area(void)260 static GtkWidget *build_map_area(void)
261 {
262 GtkWidget *map_area = guimap_build_drawingarea(gmap, MAP_WIDTH,
263 MAP_HEIGHT);
264 gtk_widget_add_events(map_area, GDK_BUTTON_PRESS_MASK);
265 g_signal_connect(G_OBJECT(map_area), "button_press_event",
266 G_CALLBACK(button_press_map_cb), NULL);
267
268 return map_area;
269 }
270
build_messages_panel(void)271 static GtkWidget *build_messages_panel(void)
272 {
273 GtkWidget *vbox;
274 GtkWidget *label;
275 GtkWidget *scroll_win;
276
277 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
278 gtk_widget_show(vbox);
279
280 /* Label for messages log */
281 label = gtk_label_new(NULL);
282 gtk_label_set_markup(GTK_LABEL(label), _("<b>Messages</b>"));
283 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
284 gtk_widget_show(label);
285 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
286
287 scroll_win = gtk_scrolled_window_new(NULL, NULL);
288 gtk_widget_set_size_request(scroll_win, -1, 80);
289 gtk_widget_show(scroll_win);
290 gtk_box_pack_start(GTK_BOX(vbox), scroll_win, TRUE, TRUE, 0);
291 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
292 GTK_POLICY_AUTOMATIC,
293 GTK_POLICY_AUTOMATIC);
294
295 messages_txt = gtk_text_view_new();
296 gtk_widget_show(messages_txt);
297 gtk_container_add(GTK_CONTAINER(scroll_win), messages_txt);
298 gtk_text_view_set_editable(GTK_TEXT_VIEW(messages_txt), FALSE);
299 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(messages_txt),
300 GTK_WRAP_WORD);
301
302 message_window_set_text(messages_txt, chat_panel);
303
304 return vbox;
305 }
306
gui_show_trade_page(gboolean show)307 void gui_show_trade_page(gboolean show)
308 {
309 /* Normal keyboard focus when visible */
310 chat_set_grab_focus_on_update(!show);
311 if (show) {
312 gtk_widget_show(trade_page);
313 gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook),
314 TRADE_PAGE);
315 } else {
316 gtk_notebook_prev_page(GTK_NOTEBOOK(map_notebook));
317 gtk_widget_hide(trade_page);
318 }
319 }
320
gui_show_quote_page(gboolean show)321 void gui_show_quote_page(gboolean show)
322 {
323 /* Normal keyboard focus when visible */
324 chat_set_grab_focus_on_update(!show);
325 if (show) {
326 gtk_widget_show(quote_page);
327 gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook),
328 QUOTE_PAGE);
329 } else {
330 gtk_notebook_prev_page(GTK_NOTEBOOK(map_notebook));
331 gtk_widget_hide(quote_page);
332 }
333 }
334
gui_theme_changed(void)335 static void gui_theme_changed(void)
336 {
337 g_assert(legend_page != NULL);
338 gtk_widget_queue_draw(legend_page);
339 gtk_widget_queue_draw(gmap->area);
340 }
341
gui_show_legend_page(gboolean show)342 void gui_show_legend_page(gboolean show)
343 {
344 if (show) {
345 gtk_widget_show(legend_page);
346 gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook),
347 LEGEND_PAGE);
348 } else
349 gtk_widget_hide(legend_page);
350 }
351
gui_show_splash_page(gboolean show,GtkWidget * chat_widget)352 void gui_show_splash_page(gboolean show, GtkWidget * chat_widget)
353 {
354 static GtkWidget *widget = NULL;
355 if (chat_widget != NULL)
356 widget = chat_widget;
357 g_assert(widget != NULL);
358
359 chat_set_grab_focus_on_update(TRUE);
360 if (show) {
361 gtk_widget_show(splash_page);
362 gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook),
363 SPLASH_PAGE);
364 gtk_widget_hide(widget);
365 } else {
366 gtk_widget_hide(splash_page);
367 gtk_notebook_set_current_page(GTK_NOTEBOOK(map_notebook),
368 MAP_PAGE);
369 gtk_widget_show(widget);
370 }
371 }
372
splash_build_page(void)373 static GtkWidget *splash_build_page(void)
374 {
375 GtkWidget *image;
376 gchar *filename;
377
378 filename = g_build_filename(DATADIR, "pixmaps", "pioneers",
379 "splash.png", NULL);
380 image = gtk_image_new_from_file(filename);
381 gtk_widget_show(image);
382 g_free(filename);
383
384 return image;
385 }
386
build_map_panel(void)387 static GtkWidget *build_map_panel(void)
388 {
389 GtkWidget *lbl;
390 GtkWidget *hbox;
391 GtkWidget *close_button;
392
393 map_notebook = gtk_notebook_new();
394 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(map_notebook), GTK_POS_TOP);
395 gtk_widget_show(map_notebook);
396
397 /* Tab page name */
398 lbl = gtk_label_new(_("Map"));
399 gtk_widget_show(lbl);
400 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
401 build_map_area(), lbl, MAP_PAGE);
402
403 hbox = create_label_with_close_button(
404 /* Tab page name */
405 _("Trade"),
406 /* Tooltip */
407 _("Finish trading"),
408 &close_button);
409 frontend_gui_register(close_button, GUI_TRADE_FINISH, "clicked");
410 trade_page = trade_build_page();
411 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
412 trade_page, hbox, TRADE_PAGE);
413 gtk_widget_hide(trade_page);
414
415 hbox = create_label_with_close_button(
416 /* Tab page name */
417 _("Quote"),
418 /* Tooltip */
419 _(""
420 "Reject domestic trade"),
421 &close_button);
422 frontend_gui_register(close_button, GUI_QUOTE_REJECT, "clicked");
423 quote_page = quote_build_page();
424 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
425 quote_page, hbox, QUOTE_PAGE);
426 gtk_widget_hide(quote_page);
427
428 /* Tab page name */
429 lbl = gtk_label_new(_("Legend"));
430 gtk_widget_show(lbl);
431 legend_page = legend_create_content();
432 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
433 legend_page, lbl, LEGEND_PAGE);
434 if (!legend_page_enabled)
435 gui_show_legend_page(FALSE);
436 theme_register_callback(G_CALLBACK(gui_theme_changed));
437
438 /* Tab page name, shown for the splash screen */
439 lbl = gtk_label_new(_("Welcome to Pioneers"));
440 gtk_widget_show(lbl);
441 splash_page = splash_build_page();
442 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
443 splash_page, lbl, SPLASH_PAGE);
444
445 return map_notebook;
446 }
447
gui_discard_show(void)448 void gui_discard_show(void)
449 {
450 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 1);
451 }
452
gui_discard_hide(void)453 void gui_discard_hide(void)
454 {
455 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 0);
456 }
457
gui_gold_show(void)458 void gui_gold_show(void)
459 {
460 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 2);
461 }
462
gui_gold_hide(void)463 void gui_gold_hide(void)
464 {
465 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 0);
466 }
467
gui_prompt_show(const gchar * message)468 void gui_prompt_show(const gchar * message)
469 {
470 gtk_label_set_text(GTK_LABEL(prompt_lbl), message);
471 /* Force resize of the notebook, this is needed because
472 * GTK does not redraw when the text in a label changes.
473 */
474 gtk_container_check_resize(GTK_CONTAINER(develop_notebook));
475 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 3);
476 }
477
gui_prompt_hide(void)478 void gui_prompt_hide(void)
479 {
480 gtk_notebook_set_current_page(GTK_NOTEBOOK(develop_notebook), 0);
481 }
482
prompt_build_page(void)483 static GtkWidget *prompt_build_page(void)
484 {
485 prompt_lbl = gtk_label_new("");
486 gtk_widget_show(prompt_lbl);
487 return prompt_lbl;
488 }
489
build_develop_panel(void)490 static GtkWidget *build_develop_panel(void)
491 {
492 develop_notebook = gtk_notebook_new();
493 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(develop_notebook), FALSE);
494 gtk_notebook_set_show_border(GTK_NOTEBOOK(develop_notebook),
495 FALSE);
496 gtk_widget_show(develop_notebook);
497
498 gtk_notebook_insert_page(GTK_NOTEBOOK(develop_notebook),
499 develop_build_page(), NULL, 0);
500 gtk_notebook_insert_page(GTK_NOTEBOOK(develop_notebook),
501 discard_build_page(), NULL, 1);
502 gtk_notebook_insert_page(GTK_NOTEBOOK(develop_notebook),
503 gold_build_page(), NULL, 2);
504 gtk_notebook_insert_page(GTK_NOTEBOOK(develop_notebook),
505 prompt_build_page(), NULL, 3);
506
507 return develop_notebook;
508 }
509
get_16_9_layout(void)510 static gboolean get_16_9_layout(void)
511 {
512 GtkWidget *paned;
513
514 g_return_val_if_fail(main_paned != NULL, FALSE);
515 g_return_val_if_fail(chat_panel != NULL, FALSE);
516
517 paned = gtk_paned_get_child1(GTK_PANED(main_paned));
518 if (gtk_widget_get_parent(chat_panel) == paned)
519 return FALSE;
520 return TRUE;
521 }
522
set_16_9_layout(gboolean layout_16_9)523 static void set_16_9_layout(gboolean layout_16_9)
524 {
525 GtkWidget *paned;
526 gboolean can_remove;
527
528 g_return_if_fail(main_paned != NULL);
529 g_return_if_fail(chat_panel != NULL);
530
531 paned = gtk_paned_get_child1(GTK_PANED(main_paned));
532
533 /* Increase reference count, otherwise it will be destroyed */
534 g_object_ref(chat_panel);
535
536 /* Initially the widget has no parent, and cannot be removed */
537 can_remove = gtk_widget_get_parent(chat_panel) != NULL;
538
539 if (layout_16_9) {
540 if (can_remove)
541 gtk_container_remove(GTK_CONTAINER(paned),
542 chat_panel);
543 gtk_container_add(GTK_CONTAINER(main_paned), chat_panel);
544 } else {
545 if (can_remove)
546 gtk_container_remove(GTK_CONTAINER(main_paned),
547 chat_panel);
548 gtk_container_add(GTK_CONTAINER(paned), chat_panel);
549 }
550 g_object_unref(chat_panel);
551 }
552
build_main_interface(void)553 static GtkWidget *build_main_interface(void)
554 {
555 GtkWidget *vbox;
556 GtkWidget *hpaned;
557 GtkWidget *vpaned;
558 GtkWidget *panel;
559
560 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
561 gtk_widget_show(hpaned);
562
563 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
564 gtk_widget_show(vbox);
565 gtk_paned_pack1(GTK_PANED(hpaned), vbox, FALSE, TRUE);
566
567 gtk_box_pack_start(GTK_BOX(vbox),
568 identity_build_panel(), FALSE, TRUE, 0);
569 gtk_box_pack_start(GTK_BOX(vbox),
570 resource_build_panel(), FALSE, TRUE, 0);
571 gtk_box_pack_start(GTK_BOX(vbox),
572 build_develop_panel(), FALSE, TRUE, 0);
573 gtk_box_pack_start(GTK_BOX(vbox),
574 player_build_summary(), TRUE, TRUE, 0);
575
576 main_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
577 gtk_widget_show(main_paned);
578
579 vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
580 gtk_widget_show(vpaned);
581
582 gtk_paned_pack1(GTK_PANED(main_paned), vpaned, TRUE, TRUE);
583
584 gtk_paned_pack1(GTK_PANED(vpaned), build_map_panel(), TRUE, TRUE);
585
586 chat_panel = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
587 gui_show_splash_page(TRUE, chat_panel);
588
589 panel = chat_build_panel();
590 frontend_gui_register(panel, GUI_DISCONNECT, NULL);
591 gtk_box_pack_start(GTK_BOX(chat_panel), panel, FALSE, TRUE, 0);
592 gtk_box_pack_start(GTK_BOX(chat_panel),
593 build_messages_panel(), TRUE, TRUE, 0);
594
595 set_16_9_layout(config_get_int_with_default
596 ("settings/layout_16_9", TRUE));
597
598 gtk_paned_pack2(GTK_PANED(hpaned), main_paned, TRUE, TRUE);
599 return hpaned;
600 }
601
theme_change_cb(GObject * gobject,G_GNUC_UNUSED gpointer user_data)602 static void theme_change_cb(GObject * gobject,
603 G_GNUC_UNUSED gpointer user_data)
604 {
605 gint idx = gtk_combo_box_get_active(GTK_COMBO_BOX(gobject));
606 MapTheme *theme = g_list_nth_data(theme_get_list(), idx);
607 if (theme != theme_get_current()) {
608 config_set_string("settings/theme", theme->name);
609 theme_set_current(theme);
610 if (gmap->surface != NULL) {
611 cairo_surface_destroy(gmap->surface);
612 gmap->surface = NULL;
613 }
614 theme_rescale(2 * gmap->x_point);
615 }
616
617 }
618
show_legend_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)619 static void show_legend_cb(GtkToggleButton * widget,
620 G_GNUC_UNUSED gpointer user_data)
621 {
622 legend_page_enabled = gtk_toggle_button_get_active(widget);
623 gui_show_legend_page(legend_page_enabled);
624 config_set_int("settings/legend_page", legend_page_enabled);
625 }
626
message_color_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)627 static void message_color_cb(GtkToggleButton * widget,
628 G_GNUC_UNUSED gpointer user_data)
629 {
630 color_messages_enabled = gtk_toggle_button_get_active(widget);
631 config_set_int("settings/color_messages", color_messages_enabled);
632 log_set_func_message_color_enable(color_messages_enabled);
633 }
634
chat_color_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)635 static void chat_color_cb(GtkToggleButton * widget,
636 G_GNUC_UNUSED gpointer user_data)
637 {
638 color_chat_enabled = gtk_toggle_button_get_active(widget);
639 config_set_int("settings/color_chat", color_chat_enabled);
640 }
641
summary_color_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)642 static void summary_color_cb(GtkToggleButton * widget,
643 G_GNUC_UNUSED gpointer user_data)
644 {
645 gboolean color_summary = gtk_toggle_button_get_active(widget);
646 config_set_int("settings/color_summary", color_summary);
647 set_color_summary(color_summary);
648 }
649
silent_mode_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)650 static void silent_mode_cb(GtkToggleButton * widget,
651 G_GNUC_UNUSED gpointer user_data)
652 {
653 GtkToggleButton *announce_button = user_data;
654
655 gboolean silent_mode = gtk_toggle_button_get_active(widget);
656 config_set_int("settings/silent_mode", silent_mode);
657 set_silent_mode(silent_mode);
658 gtk_toggle_button_set_inconsistent(announce_button, silent_mode);
659 gtk_widget_set_sensitive(GTK_WIDGET(announce_button),
660 !silent_mode);
661 }
662
announce_player_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)663 static void announce_player_cb(GtkToggleButton * widget,
664 G_GNUC_UNUSED gpointer user_data)
665 {
666 gboolean announce_player = gtk_toggle_button_get_active(widget);
667 config_set_int("settings/announce_player", announce_player);
668 set_announce_player(announce_player);
669 }
670
toggle_16_9_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)671 static void toggle_16_9_cb(GtkToggleButton * widget,
672 G_GNUC_UNUSED gpointer user_data)
673 {
674 gboolean layout_16_9 = gtk_toggle_button_get_active(widget);
675 config_set_int("settings/layout_16_9", layout_16_9);
676 set_16_9_layout(layout_16_9);
677 }
678
toggle_notifications_cb(GtkToggleButton * widget,G_GNUC_UNUSED gpointer user_data)679 static void toggle_notifications_cb(GtkToggleButton * widget,
680 G_GNUC_UNUSED gpointer user_data)
681 {
682 gboolean show_notifications = gtk_toggle_button_get_active(widget);
683 config_set_int("settings/show_notifications", show_notifications);
684 set_show_notifications(show_notifications);
685 }
686
showhide_toolbar_cb(GObject * gobject,G_GNUC_UNUSED gpointer user_data)687 void showhide_toolbar_cb(GObject * gobject,
688 G_GNUC_UNUSED gpointer user_data)
689 {
690 gui_set_toolbar_visible(gtk_check_menu_item_get_active
691 (GTK_CHECK_MENU_ITEM(gobject)));
692 }
693
toolbar_shortcuts_cb(void)694 static void toolbar_shortcuts_cb(void)
695 {
696 gui_toolbar_show_accelerators(!toolbar_show_accelerators);
697 }
698
get_charity_enabled(void)699 gboolean get_charity_enabled(void)
700 {
701 return charity_enabled;
702 }
703
set_charity_enabled(gboolean new_charity_enabled)704 void set_charity_enabled(gboolean new_charity_enabled)
705 {
706 if (new_charity_enabled != charity_enabled) {
707 charity_enabled = new_charity_enabled;
708 config_set_int("settings/charity_enabled",
709 charity_enabled);
710 }
711 }
712
get_automatic_roll(void)713 TAutomaticRoll get_automatic_roll(void)
714 {
715 return automatic_roll;
716 }
717
set_automatic_roll(TAutomaticRoll new_automatic_roll)718 void set_automatic_roll(TAutomaticRoll new_automatic_roll)
719 {
720 if (new_automatic_roll != automatic_roll) {
721 automatic_roll = new_automatic_roll;
722 config_set_int("settings/automatic_roll", automatic_roll);
723 }
724 }
725
automatic_roll_changed_cb(GtkComboBox * widget,G_GNUC_UNUSED gpointer user_data)726 static void automatic_roll_changed_cb(GtkComboBox * widget,
727 G_GNUC_UNUSED gpointer user_data)
728 {
729 GtkTreeIter iter;
730
731 if (gtk_combo_box_get_active_iter(widget, &iter)) {
732 gint value;
733 gtk_tree_model_get(gtk_combo_box_get_model(widget), &iter,
734 1, &value, -1);
735 set_automatic_roll(value);
736 }
737 }
738
preferences_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)739 void preferences_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
740 {
741 GtkWidget *silent_mode_widget;
742 GtkWidget *widget;
743 GtkWidget *dlg_vbox;
744 GtkWidget *theme_label;
745 GtkWidget *theme_list;
746 GtkWidget *layout;
747 GtkListStore *auto_roll_list;
748 GtkCellRenderer *cell;
749 GtkTreeIter iter;
750 GtkTreeIter active_iter;
751
752 guint row;
753 gint color_summary;
754 GList *theme_elt;
755 int i;
756
757 if (preferences_dlg != NULL) {
758 gtk_window_present(GTK_WINDOW(preferences_dlg));
759 return;
760 };
761
762 /* Caption of preferences dialog */
763 preferences_dlg = gtk_dialog_new_with_buttons(_(""
764 "Pioneers Preferences"),
765 GTK_WINDOW
766 (user_data),
767 GTK_DIALOG_DESTROY_WITH_PARENT,
768 /* Button text */
769 _("_Close"),
770 GTK_RESPONSE_CLOSE,
771 NULL);
772 gtk_dialog_set_default_response(GTK_DIALOG(preferences_dlg),
773 GTK_RESPONSE_CLOSE);
774 g_signal_connect(G_OBJECT(preferences_dlg), "destroy",
775 G_CALLBACK(gtk_widget_destroyed),
776 &preferences_dlg);
777 g_signal_connect(G_OBJECT(preferences_dlg), "response",
778 G_CALLBACK(gtk_widget_destroy), NULL);
779 gtk_widget_show(preferences_dlg);
780
781 dlg_vbox =
782 gtk_dialog_get_content_area(GTK_DIALOG(preferences_dlg));
783 gtk_widget_show(dlg_vbox);
784
785 layout = gtk_grid_new();
786 gtk_grid_set_row_spacing(GTK_GRID(layout), 3);
787 gtk_grid_set_column_spacing(GTK_GRID(layout), 5);
788 gtk_widget_show(layout);
789 gtk_box_pack_start(GTK_BOX(dlg_vbox), layout, FALSE, TRUE, 0);
790 gtk_container_set_border_width(GTK_CONTAINER(layout), 5);
791
792 row = 0;
793
794 theme_list = gtk_combo_box_text_new();
795 gtk_widget_set_hexpand(theme_list, TRUE);
796 /* Label for changing the theme, in the preferences dialog */
797 theme_label = gtk_label_new(_("Theme:"));
798 gtk_label_set_xalign(GTK_LABEL(theme_label), 0.0);
799 gtk_widget_show(theme_list);
800 gtk_widget_show(theme_label);
801
802 for (i = 0, theme_elt = theme_get_list();
803 theme_elt != NULL; ++i, theme_elt = g_list_next(theme_elt)) {
804 MapTheme *theme = theme_elt->data;
805 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT
806 (theme_list), theme->name);
807 if (theme == theme_get_current())
808 gtk_combo_box_set_active(GTK_COMBO_BOX(theme_list),
809 i);
810 }
811 g_signal_connect(G_OBJECT(theme_list), "changed",
812 G_CALLBACK(theme_change_cb), NULL);
813
814 gtk_grid_attach(GTK_GRID(layout), theme_label, 0, row, 1, 1);
815 gtk_grid_attach(GTK_GRID(layout), theme_list, 1, row, 1, 1);
816 gtk_widget_set_tooltip_text(theme_list,
817 /* Tooltip for changing the theme in the preferences dialog */
818 _("Choose one of the themes"));
819 row++;
820
821 /* Label for the option to show the legend */
822 widget = gtk_check_button_new_with_label(_("Show legend"));
823 gtk_widget_show(widget);
824 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
825 legend_page_enabled);
826 g_signal_connect(G_OBJECT(widget), "toggled",
827 G_CALLBACK(show_legend_cb), NULL);
828 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
829 gtk_widget_set_tooltip_text(widget,
830 /* Tooltip for the option to show the legend */
831 _(""
832 "Show the legend as a page beside the map"));
833 row++;
834
835 /* Label for the option to display log messages in color */
836 widget = gtk_check_button_new_with_label(_("Messages with color"));
837 gtk_widget_show(widget);
838 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
839 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
840 color_messages_enabled);
841 g_signal_connect(G_OBJECT(widget), "toggled",
842 G_CALLBACK(message_color_cb), NULL);
843 gtk_widget_set_tooltip_text(widget,
844 /* Tooltip for the option to display log messages in color */
845 _("Show new messages with color"));
846 row++;
847
848 widget = gtk_check_button_new_with_label(
849 /* Label for the option to display chat in color of player */
850 _(""
851 "Chat in color of player"));
852 gtk_widget_show(widget);
853 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
854 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
855 color_chat_enabled);
856 g_signal_connect(G_OBJECT(widget), "toggled",
857 G_CALLBACK(chat_color_cb), NULL);
858 gtk_widget_set_tooltip_text(widget,
859 /* Tooltip for the option to display chat in color of player */
860 _(""
861 "Show new chat messages in the color of the player"));
862 row++;
863
864 /* Label for the option to display the summary with colors */
865 widget = gtk_check_button_new_with_label(_("Summary with color"));
866 gtk_widget_show(widget);
867 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
868 color_summary =
869 config_get_int_with_default("settings/color_summary", TRUE);
870 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), color_summary); /* @todo RC use correct variable */
871 g_signal_connect(G_OBJECT(widget), "toggled",
872 G_CALLBACK(summary_color_cb), NULL);
873 gtk_widget_set_tooltip_text(widget,
874 /* Tooltip for the option to display the summary with colors */
875 _("Use colors in the player summary"));
876 row++;
877
878 widget =
879 /* Label for the option to display keyboard accelerators in the toolbar */
880 gtk_check_button_new_with_label(_("Toolbar with shortcuts"));
881 gtk_widget_show(widget);
882 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
883 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
884 toolbar_show_accelerators);
885 g_signal_connect(G_OBJECT(widget), "toggled",
886 G_CALLBACK(toolbar_shortcuts_cb), NULL);
887 gtk_widget_set_tooltip_text(widget,
888 /* Tooltip for the option to display keyboard accelerators in the toolbar */
889 _(""
890 "Show keyboard shortcuts in the toolbar"));
891 row++;
892
893 silent_mode_widget =
894 /* Label for the option to disable all sounds */
895 gtk_check_button_new_with_label(_("Silent mode"));
896 gtk_widget_show(silent_mode_widget);
897 gtk_grid_attach(GTK_GRID(layout), silent_mode_widget, 0, row, 2,
898 1);
899 gtk_widget_set_tooltip_text(silent_mode_widget,
900 /* Tooltip for the option to disable all sounds */
901 _(""
902 "In silent mode no sounds are made"));
903 row++;
904
905 widget =
906 /* Label for the option to announce when players/spectators enter */
907 gtk_check_button_new_with_label(_("Announce new players"));
908 gtk_widget_show(widget);
909 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
910 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
911 get_announce_player());
912 g_signal_connect(G_OBJECT(widget), "toggled",
913 G_CALLBACK(announce_player_cb), NULL);
914 gtk_widget_set_tooltip_text(widget,
915 /* Tooltip for the option to use sound when players/spectators enter */
916 _(""
917 "Make a sound when a new player or spectator enters the game"));
918 row++;
919
920 /* Silent mode widget is connected an initialized after the announce button */
921 g_signal_connect(G_OBJECT(silent_mode_widget), "toggled",
922 G_CALLBACK(silent_mode_cb), widget);
923 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(silent_mode_widget),
924 get_silent_mode());
925
926 #ifdef HAVE_NOTIFY
927 /* Label for the option to use the notifications. */
928 widget = gtk_check_button_new_with_label(_("Show notifications"));
929 gtk_widget_show(widget);
930 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
931 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
932 get_show_notifications());
933 g_signal_connect(G_OBJECT(widget), "toggled",
934 G_CALLBACK(toggle_notifications_cb), NULL);
935 gtk_widget_set_tooltip_text(widget,
936 /* Tooltip for notifications option. */
937 _("Show notifications when it's your "
938 "turn or when new trade is available"));
939 row++;
940 #endif
941
942 /* Label for the option to use the 16:9 layout. */
943 widget = gtk_check_button_new_with_label(_("Use 16:9 layout"));
944 gtk_widget_show(widget);
945 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
946 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
947 get_16_9_layout());
948 g_signal_connect(G_OBJECT(widget), "toggled",
949 G_CALLBACK(toggle_16_9_cb), NULL);
950 gtk_widget_set_tooltip_text(widget,
951 /* Tooltip for 16:9 option. */
952 _(""
953 "Use a 16:9 friendly layout for the window"));
954 row++;
955
956 auto_roll_list = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
957 gtk_list_store_append(auto_roll_list, &iter);
958 gtk_list_store_set(auto_roll_list, &iter,
959 0, _("Roll the dice manually each turn"),
960 1, ROLL_MANUALLY, -1);
961 if (get_automatic_roll() == ROLL_MANUALLY) {
962 active_iter = iter;
963 }
964 gtk_list_store_append(auto_roll_list, &iter);
965 gtk_list_store_set(auto_roll_list, &iter,
966 0,
967 _(""
968 "Roll the dice automatically, except when you have a soldier card"),
969 1, ROLL_AUTOMATICALLY_EXCEPT_WITH_SOLDIER_CARD,
970 -1);
971 if (get_automatic_roll() ==
972 ROLL_AUTOMATICALLY_EXCEPT_WITH_SOLDIER_CARD) {
973 active_iter = iter;
974 }
975 gtk_list_store_append(auto_roll_list, &iter);
976 gtk_list_store_set(auto_roll_list, &iter,
977 0,
978 _(""
979 "Roll the dice automatically, except when you have a development card"),
980 1, ROLL_AUTOMATICALLY_EXCEPT_WITH_RESOURCE_CARD,
981 -1);
982 if (get_automatic_roll() ==
983 ROLL_AUTOMATICALLY_EXCEPT_WITH_RESOURCE_CARD) {
984 active_iter = iter;
985 }
986 gtk_list_store_append(auto_roll_list, &iter);
987 gtk_list_store_set(auto_roll_list, &iter,
988 0, _("Roll the dice automatically"),
989 1, ROLL_AUTOMATICALLY, -1);
990 if (get_automatic_roll() == ROLL_AUTOMATICALLY) {
991 active_iter = iter;
992 }
993 widget =
994 gtk_combo_box_new_with_model(GTK_TREE_MODEL(auto_roll_list));
995 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(widget), &active_iter);
996
997 cell = gtk_cell_renderer_text_new();
998 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), cell, TRUE);
999 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget),
1000 cell, "text", 0, NULL);
1001
1002 gtk_widget_show(widget);
1003 gtk_grid_attach(GTK_GRID(layout), widget, 0, row, 2, 1);
1004 g_signal_connect(G_OBJECT(widget), "changed",
1005 G_CALLBACK(automatic_roll_changed_cb), NULL);
1006 gtk_widget_set_tooltip_text(widget,
1007 /* Tooltip for automatic roll option. */
1008 _(""
1009 "Automate the rolling of the dice"));
1010 row++;
1011
1012 }
1013
help_about_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)1014 void help_about_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
1015 {
1016 aboutbox_display(GTK_WINDOW(user_data),
1017 /* Caption of about box */
1018 _("About Pioneers"));
1019 }
1020
game_legend_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)1021 void game_legend_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
1022 {
1023 legend_create_dlg(GTK_WINDOW(user_data));
1024 }
1025
game_histogram_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)1026 void game_histogram_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
1027 {
1028 histogram_create_dlg(GTK_WINDOW(user_data));
1029 }
1030
game_settings_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)1031 void game_settings_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
1032 {
1033 settings_create_dlg(GTK_WINDOW(user_data));
1034 }
1035
1036 #ifdef HAVE_HELP
help_manual_cb(G_GNUC_UNUSED GObject * gobject,gpointer user_data)1037 void help_manual_cb(G_GNUC_UNUSED GObject * gobject, gpointer user_data)
1038 {
1039 GError *error = NULL;
1040 gtk_show_uri_on_window(GTK_WINDOW(user_data), "help:pioneers",
1041 GDK_CURRENT_TIME, &error);
1042 if (error) {
1043 log_message(MSG_ERROR, "%s: %s\n", _("Show the manual"),
1044 error->message);
1045 g_error_free(error);
1046 }
1047 }
1048 #endif
1049
getAction(GuiEvent id)1050 static GAction *getAction(GuiEvent id)
1051 {
1052 const gchar *path = NULL;
1053 #ifdef ADMIN_GTK
1054 frontend_gui_register_action(gtk_ui_manager_get_action
1055 (manager,
1056 "ui/MainMenu/GameMenu/GameAdmin"),
1057 GUI_CONNECT);
1058 #endif
1059
1060 switch (id) {
1061 case GUI_CONNECT:
1062 path = "action_game_new";
1063 break;
1064 case GUI_DISCONNECT:
1065 path = "action_game_leave";
1066 break;
1067 case GUI_CHANGE_NAME:
1068 path = "action_player_name";
1069 break;
1070 case GUI_ROLL:
1071 path = "action_roll_dice";
1072 break;
1073 case GUI_TRADE:
1074 path = "action_trade";
1075 break;
1076 case GUI_UNDO:
1077 path = "action_undo";
1078 break;
1079 case GUI_FINISH:
1080 path = "action_finish";
1081 break;
1082 case GUI_ROAD:
1083 path = "action_build_road";
1084 break;
1085 case GUI_SHIP:
1086 path = "action_build_ship";
1087 break;
1088 case GUI_MOVE_SHIP:
1089 path = "action_move_ship";
1090 break;
1091 case GUI_BRIDGE:
1092 path = "action_build_bridge";
1093 break;
1094 case GUI_SETTLEMENT:
1095 path = "action_build_settlement";
1096 break;
1097 case GUI_CITY:
1098 path = "action_build_city";
1099 break;
1100 case GUI_BUY_DEVELOP:
1101 path = "action_buy_development";
1102 break;
1103 case GUI_CITY_WALL:
1104 path = "action_build_city_wall";
1105 break;
1106 default:
1107 break;
1108 };
1109
1110 if (!path)
1111 return NULL;
1112
1113 return g_action_map_lookup_action(G_ACTION_MAP(action_group),
1114 path);
1115 }
1116
1117 /** Set the visibility of the toolbar */
gui_set_toolbar_visible(gboolean visible)1118 static void gui_set_toolbar_visible(gboolean visible)
1119 {
1120 GtkWidget *toolbar =
1121 GTK_WIDGET(gtk_builder_get_object(builder, "toolbar"));
1122
1123 if (visible)
1124 gtk_widget_show(GTK_WIDGET(toolbar));
1125 else
1126 gtk_widget_hide(GTK_WIDGET(toolbar));
1127 config_set_int("settings/show_toolbar", visible);
1128 }
1129
1130 /* Note:
1131 * 1. the accelerators are not translated
1132 * 2. the accelerators are duplicated here from the .ui file
1133 * 3. the UI file has Roll Dice\nF1 to ensure the proper initial size
1134 */
1135 /* *INDENT-OFF* */
1136 static struct {
1137 const gchar *text;
1138 const gchar *accelerator;
1139 } toolbar_accelerators[] = {
1140 { N_("Roll Dice"), "F1" },
1141 { N_("Trade"), "F2" },
1142 { N_("Undo"), "F3" },
1143 { N_("Finish") , "F4" },
1144 { N_("Road"), "F5" },
1145 { N_("Ship"), "F6" },
1146 { N_("Move Ship"), "F7" },
1147 { N_("Bridge"), "F8" },
1148 { N_("Settlement"), "F9" },
1149 { N_("City"), "F10" },
1150 { N_("Develop"), "F11" },
1151 { N_("City Wall"), NULL },
1152 };
1153 /* *INDENT-ON* */
1154
1155 /** Show the accelerators in the toolbar */
gui_toolbar_show_accelerators(gboolean show_accelerators)1156 static void gui_toolbar_show_accelerators(gboolean show_accelerators)
1157 {
1158 GtkToolbar *tb;
1159 gint n, i;
1160
1161 toolbar_show_accelerators = show_accelerators;
1162
1163 tb = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
1164 g_return_if_fail(tb != NULL);
1165
1166 n = gtk_toolbar_get_n_items(tb);
1167 for (i = 0; i < n; i++) {
1168 GtkToolItem *ti;
1169 GtkToolButton *tbtn;
1170 gchar *text;
1171 guint j;
1172
1173 ti = gtk_toolbar_get_nth_item(tb, i);
1174 tbtn = GTK_TOOL_BUTTON(ti);
1175 g_assert(tbtn != NULL);
1176
1177 text = g_strdup(gtk_tool_button_get_label(tbtn));
1178 if (strchr(text, '\n'))
1179 *strchr(text, '\n') = '\0';
1180 /* Find the matching entry */
1181 for (j = 0; j < G_N_ELEMENTS(toolbar_accelerators); j++) {
1182 if (strcmp(text, _(toolbar_accelerators[j].text))
1183 == 0) {
1184 if (show_accelerators) {
1185 gchar *label;
1186
1187 if (toolbar_accelerators
1188 [j].accelerator == NULL)
1189 label =
1190 g_strdup_printf
1191 ("%s\n", text);
1192 else {
1193 label =
1194 g_strdup_printf
1195 ("%s\n(%s)",
1196 text,
1197 toolbar_accelerators
1198 [j].accelerator);
1199 }
1200 gtk_tool_button_set_label
1201 (tbtn, label);
1202 g_free(label);
1203 } else {
1204 gtk_tool_button_set_label
1205 (tbtn, text);
1206 }
1207 break;
1208 }
1209 }
1210 g_free(text);
1211 }
1212 config_set_int("settings/toolbar_show_accelerators",
1213 toolbar_show_accelerators);
1214 }
1215
1216 /** Show or hide a button in the toolbar */
gui_toolbar_show_button(const gchar * id,gboolean visible)1217 static void gui_toolbar_show_button(const gchar * id, gboolean visible)
1218 {
1219 GtkToolItem *item =
1220 GTK_TOOL_ITEM(gtk_builder_get_object(builder, id));
1221
1222 g_return_if_fail(item != NULL);
1223 gtk_tool_item_set_visible_horizontal(item, visible);
1224 }
1225
gui_rules_register_callback(GCallback callback)1226 void gui_rules_register_callback(GCallback callback)
1227 {
1228 rules_callback_list = g_list_append(rules_callback_list, callback);
1229 }
1230
gui_set_game_params(const GameParams * params)1231 void gui_set_game_params(const GameParams * params)
1232 {
1233 GList *list;
1234 GtkWidget *label;
1235
1236 gmap->map = params->map;
1237 gmap->player_num = my_player_num();
1238 gtk_widget_queue_resize(gmap->area);
1239
1240 gui_toolbar_show_button("BuildRoad",
1241 params->num_build_type[BUILD_ROAD] > 0);
1242 gui_toolbar_show_button("BuildShip",
1243 params->num_build_type[BUILD_SHIP] > 0);
1244 gui_toolbar_show_button("MoveShip",
1245 params->num_build_type[BUILD_SHIP] > 0);
1246 gui_toolbar_show_button("BuildBridge",
1247 params->num_build_type[BUILD_BRIDGE] > 0);
1248 /* In theory, it is possible to play a game without cities */
1249 gui_toolbar_show_button("BuildCity",
1250 params->num_build_type[BUILD_CITY] > 0);
1251 gui_toolbar_show_button("BuildCityWall",
1252 params->num_build_type[BUILD_CITY_WALL] >
1253 0);
1254
1255 identity_draw();
1256
1257 gui_set_vp_target_value(params->victory_points);
1258
1259 list = rules_callback_list;
1260 while (list) {
1261 G_CALLBACK(list->data) ();
1262 list = g_list_next(list);
1263 }
1264
1265 label =
1266 gtk_notebook_get_tab_label(GTK_NOTEBOOK(map_notebook),
1267 legend_page);
1268 g_object_ref(label);
1269
1270 gtk_widget_destroy(legend_page);
1271 legend_page = legend_create_content();
1272 gtk_notebook_insert_page(GTK_NOTEBOOK(map_notebook),
1273 legend_page, label, LEGEND_PAGE);
1274 if (!legend_page_enabled)
1275 gui_show_legend_page(FALSE);
1276 g_object_unref(label);
1277 }
1278
build_status_bar(void)1279 static GtkWidget *build_status_bar(void)
1280 {
1281 GtkWidget *vsep;
1282
1283 app_bar = gtk_statusbar_new();
1284 gtk_widget_show(app_bar);
1285
1286 vp_target_status = gtk_label_new("");
1287 gtk_widget_show(vp_target_status);
1288 gtk_box_pack_start(GTK_BOX(app_bar), vp_target_status, FALSE, TRUE,
1289 0);
1290
1291 vsep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
1292 gtk_widget_show(vsep);
1293 gtk_box_pack_start(GTK_BOX(app_bar), vsep, FALSE, TRUE, 0);
1294
1295 /* Network status: offline */
1296 net_status = gtk_label_new(_("Offline"));
1297 gtk_widget_show(net_status);
1298 gtk_box_pack_start(GTK_BOX(app_bar), net_status, FALSE, TRUE, 0);
1299
1300 vsep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
1301 gtk_widget_show(vsep);
1302 gtk_box_pack_start(GTK_BOX(app_bar), vsep, FALSE, TRUE, 0);
1303
1304 gtk_box_pack_start(GTK_BOX(app_bar),
1305 player_build_turn_area(), FALSE, TRUE, 0);
1306
1307 /* Initial text in status bar */
1308 gui_set_instructions(_("Welcome to Pioneers!"));
1309
1310 return app_bar;
1311 }
1312
register_pixmaps(void)1313 static void register_pixmaps(void)
1314 {
1315 GtkIconTheme *iconTheme = gtk_icon_theme_get_default();
1316 gchar *path;
1317
1318 path = g_build_filename(DATADIR, "pixmaps", "pioneers", NULL);
1319 gtk_icon_theme_append_search_path(iconTheme, path);
1320 g_free(path);
1321 }
1322
add_guievent_action(GActionGroup * action_group,const gchar * name,GuiEvent event)1323 static void add_guievent_action(GActionGroup * action_group,
1324 const gchar * name, GuiEvent event)
1325 {
1326 GSimpleAction *action = g_simple_action_new(name, NULL);
1327 g_signal_connect(action, "activate",
1328 G_CALLBACK(redirect_gui_event_cb),
1329 g_variant_new_int32(event));
1330 g_action_map_add_action(G_ACTION_MAP(action_group),
1331 G_ACTION(action));
1332 }
1333
gui_build_interface(void)1334 GtkWidget *gui_build_interface(void)
1335 {
1336 GtkWidget *vbox;
1337 gchar *icon_file;
1338 GSimpleAction *action;
1339
1340 player_init();
1341
1342 gmap = guimap_new();
1343
1344 register_pixmaps();
1345
1346 builder =
1347 gtk_builder_new_from_resource
1348 ("/net/sourceforge/pio/client/gtk/client.ui");
1349 app_window =
1350 GTK_WIDGET(gtk_builder_get_object(builder, "toplevel"));
1351 /* The name of the application */
1352 gtk_window_set_title(GTK_WINDOW(app_window), _("Pioneers"));
1353 gtk_builder_connect_signals(builder, app_window);
1354
1355 vbox = GTK_WIDGET(gtk_builder_get_object(builder, "vbox"));
1356
1357 icon_file =
1358 g_build_filename(DATADIR, "pixmaps", PIONEERS_ICON_FILE, NULL);
1359 if (g_file_test(icon_file, G_FILE_TEST_EXISTS)) {
1360 gtk_window_set_default_icon_from_file(icon_file, NULL);
1361 } else {
1362 /* Missing pixmap, main icon file */
1363 g_warning("Pixmap not found: %s", icon_file);
1364 }
1365 g_free(icon_file);
1366
1367 color_chat_enabled =
1368 config_get_int_with_default("settings/color_chat", TRUE);
1369
1370 color_messages_enabled =
1371 config_get_int_with_default("settings/color_messages", TRUE);
1372 log_set_func_message_color_enable(color_messages_enabled);
1373
1374 set_color_summary(config_get_int_with_default
1375 ("settings/color_summary", TRUE));
1376
1377 set_silent_mode(config_get_int_with_default
1378 ("settings/silent_mode", FALSE));
1379 set_announce_player(config_get_int_with_default
1380 ("settings/announce_player", TRUE));
1381 set_show_notifications(config_get_int_with_default
1382 ("settings/show_notifications", TRUE));
1383 set_charity_enabled(config_get_int_with_default
1384 ("settings/charity_enabled", FALSE));
1385 set_automatic_roll(config_get_int_with_default
1386 ("settings/automatic_roll",
1387 get_automatic_roll()));
1388
1389 legend_page_enabled =
1390 config_get_int_with_default("settings/legend_page", FALSE);
1391
1392 gtk_box_pack_start(GTK_BOX(vbox), build_main_interface(), TRUE,
1393 TRUE, 0);
1394 gtk_box_pack_start(GTK_BOX(vbox), build_status_bar(), FALSE, FALSE,
1395 0);
1396
1397 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
1398 (gtk_builder_get_object
1399 (builder,
1400 "toolbar_visible")),
1401 config_get_int_with_default
1402 ("settings/show_toolbar", TRUE));
1403
1404 g_signal_connect(G_OBJECT(app_window), "key_press_event",
1405 G_CALLBACK(hotkeys_handler), NULL);
1406
1407 gtk_widget_show(app_window);
1408
1409 action_group = G_ACTION_GROUP(g_simple_action_group_new());
1410 add_guievent_action(action_group, "action_game_new", GUI_CONNECT);
1411 action = g_simple_action_new("action_game_leave", NULL);
1412 g_signal_connect(action, "activate",
1413 G_CALLBACK(game_leave_cb), NULL);
1414 g_action_map_add_action(G_ACTION_MAP(action_group),
1415 G_ACTION(action));
1416 add_guievent_action(action_group, "action_player_name",
1417 GUI_CHANGE_NAME);
1418 add_guievent_action(action_group, "action_roll_dice", GUI_ROLL);
1419 add_guievent_action(action_group, "action_trade", GUI_TRADE);
1420 add_guievent_action(action_group, "action_undo", GUI_UNDO);
1421 add_guievent_action(action_group, "action_finish", GUI_FINISH);
1422 add_guievent_action(action_group, "action_build_road", GUI_ROAD);
1423 add_guievent_action(action_group, "action_build_ship", GUI_SHIP);
1424 add_guievent_action(action_group, "action_move_ship",
1425 GUI_MOVE_SHIP);
1426 add_guievent_action(action_group, "action_build_bridge",
1427 GUI_BRIDGE);
1428 add_guievent_action(action_group,
1429 "action_build_settlement", GUI_SETTLEMENT);
1430 add_guievent_action(action_group, "action_build_city", GUI_CITY);
1431 add_guievent_action(action_group, "action_buy_development",
1432 GUI_BUY_DEVELOP);
1433 add_guievent_action(action_group, "action_build_city_wall",
1434 GUI_CITY_WALL);
1435 gtk_widget_insert_action_group(app_window, "win", action_group);
1436
1437 frontend_gui_register_action(getAction(GUI_CONNECT), GUI_CONNECT);
1438 frontend_gui_register_action(getAction(GUI_DISCONNECT),
1439 GUI_DISCONNECT);
1440 #ifdef ADMIN_GTK
1441 /** @todo RC 2005-05-26 Admin interface: Not tested */
1442 frontend_gui_register_action(gtk_ui_manager_get_action
1443 (manager,
1444 "ui/MainMenu/GameMenu/GameAdmin"),
1445 GUI_ADMIN);
1446 gtk_menu_item_set_visible(GTK_MENU_ITEM
1447 (gtk_builder_get_object
1448 (builder, "admin")), TRUE);
1449 #endif
1450 frontend_gui_register_action(getAction(GUI_CHANGE_NAME),
1451 GUI_CHANGE_NAME);
1452 frontend_gui_register_action(getAction(GUI_ROLL), GUI_ROLL);
1453 frontend_gui_register_action(getAction(GUI_TRADE), GUI_TRADE);
1454 frontend_gui_register_action(getAction(GUI_UNDO), GUI_UNDO);
1455 frontend_gui_register_action(getAction(GUI_FINISH), GUI_FINISH);
1456 frontend_gui_register_action(getAction(GUI_ROAD), GUI_ROAD);
1457 frontend_gui_register_action(getAction(GUI_SHIP), GUI_SHIP);
1458 frontend_gui_register_action(getAction(GUI_MOVE_SHIP),
1459 GUI_MOVE_SHIP);
1460 frontend_gui_register_action(getAction(GUI_BRIDGE), GUI_BRIDGE);
1461 frontend_gui_register_action(getAction(GUI_SETTLEMENT),
1462 GUI_SETTLEMENT);
1463 frontend_gui_register_action(getAction(GUI_CITY), GUI_CITY);
1464 frontend_gui_register_action(getAction(GUI_BUY_DEVELOP),
1465 GUI_BUY_DEVELOP);
1466 frontend_gui_register_action(getAction(GUI_CITY_WALL),
1467 GUI_CITY_WALL);
1468 #if 0
1469 frontend_gui_register_destroy(gtk_ui_manager_get_action
1470 (manager, "GameQuit"), GUI_QUIT);
1471 #endif
1472 #ifdef HAVE_HELP
1473 gtk_widget_set_visible(GTK_WIDGET
1474 (gtk_builder_get_object
1475 (builder, "help_manual")), TRUE);
1476 #endif
1477
1478
1479 gui_toolbar_show_button("BuildShip", FALSE);
1480 gui_toolbar_show_button("MoveShip", FALSE);
1481 gui_toolbar_show_button("BuildBridge", FALSE);
1482 gui_toolbar_show_button("BuildCityWall", FALSE);
1483
1484 gui_toolbar_show_accelerators(config_get_int_with_default
1485 ("settings/toolbar_show_accelerators",
1486 TRUE));
1487
1488 gtk_widget_show(app_window);
1489 g_signal_connect(G_OBJECT(app_window), "delete_event",
1490 G_CALLBACK(game_quit_cb), NULL);
1491
1492 return app_window;
1493 }
1494
gui_set_show_no_setup_nodes(gboolean show)1495 void gui_set_show_no_setup_nodes(gboolean show)
1496 {
1497 guimap_set_show_no_setup_nodes(gmap, show);
1498 }
1499
frontend_get_map(void)1500 Map *frontend_get_map(void)
1501 {
1502 g_return_val_if_fail(gmap != NULL, NULL);
1503 return gmap->map;
1504 }
1505
frontend_set_map(Map * map)1506 void frontend_set_map(Map * map)
1507 {
1508 g_assert(gmap != NULL);
1509 gmap->map = map;
1510 }
1511