Freeciv-3.2: /fast/freeciv/nightly/S3_2/client/gui-gtk-3.22/gui_stuff.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
gui_stuff.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 <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <gtk/gtk.h>
24#include <gdk/gdkkeysyms.h>
25
26/* utility */
27#include "fcintl.h"
28#include "log.h"
29#include "mem.h"
30#include "support.h"
31
32/* client */
33#include "options.h"
34
35/* client/gui-gtk-3.22 */
36#include "colors.h"
37#include "gui_main.h"
38
39#include "gui_stuff.h"
40
41
42 static GList *dialog_list;
43
44 static GtkSizeGroup *gui_action;
45
46 static GtkCssProvider *dlg_tab_provider = NULL;
47
48
49/**********************************************************************/
52 void gtk_expose_now(GtkWidget *w)
53{
54 gtk_widget_queue_draw(w);
55}
56
57/**********************************************************************/
60 void set_relative_window_position(GtkWindow *ref, GtkWindow *w, int px, int py)
61{
62 gint x, y, width, height;
63
64 gtk_window_get_position(ref, &x, &y);
65 gtk_window_get_size(ref, &width, &height);
66
67 x += px * width / 100;
68 y += py * height / 100;
69
70 gtk_window_move(w, x, y);
71}
72
73/**********************************************************************/
76 GtkWidget *icon_label_button_new(const gchar *icon_name,
77 const gchar *label_text)
78{
79 GtkWidget *button;
80 GtkWidget *image;
81
82 button = gtk_button_new_with_mnemonic(label_text);
83
84 if (icon_name != NULL) {
85 image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON);
86 gtk_button_set_image(GTK_BUTTON(button), image);
87 }
88
89 return button;
90}
91
92/**********************************************************************/
96 void gtk_stockbutton_set_label(GtkWidget *button, const gchar *label_text)
97{
98 gtk_button_set_label(GTK_BUTTON(button), label_text);
99}
100
101/**********************************************************************/
111 void intl_slist(int n, const char **s, bool *done)
112{
113 int i;
114
115 if (!*done) {
116 for (i = 0; i < n; i++) {
117 s[i] = Q_(s[i]);
118 }
119
120 *done = TRUE;
121 }
122}
123
124/**********************************************************************/
127 void itree_begin(GtkTreeModel *model, ITree *it)
128{
129 it->model = model;
130 it->end = !gtk_tree_model_get_iter_first(it->model, &it->it);
131}
132
133/**********************************************************************/
136 gboolean itree_end(ITree *it)
137{
138 return it->end;
139}
140
141/**********************************************************************/
144 void itree_next(ITree *it)
145{
146 it->end = !gtk_tree_model_iter_next(it->model, &it->it);
147}
148
149/**********************************************************************/
152 void itree_set(ITree *it, ...)
153{
154 va_list ap;
155
156 va_start(ap, it);
157 gtk_tree_store_set_valist(GTK_TREE_STORE(it->model), &it->it, ap);
158 va_end(ap);
159}
160
161/**********************************************************************/
164 void itree_get(ITree *it, ...)
165{
166 va_list ap;
167
168 va_start(ap, it);
169 gtk_tree_model_get_valist(it->model, &it->it, ap);
170 va_end(ap);
171}
172
173/**********************************************************************/
176 void tstore_append(GtkTreeStore *store, ITree *it, ITree *parent)
177{
178 it->model = GTK_TREE_MODEL(store);
179 if (parent) {
180 gtk_tree_store_append(GTK_TREE_STORE(it->model), &it->it, &parent->it);
181 } else {
182 gtk_tree_store_append(GTK_TREE_STORE(it->model), &it->it, NULL);
183 }
184 it->end = FALSE;
185}
186
187/**********************************************************************/
190 gboolean itree_is_selected(GtkTreeSelection *selection, ITree *it)
191{
192 return gtk_tree_selection_iter_is_selected(selection, &it->it);
193}
194
195/**********************************************************************/
198 void itree_select(GtkTreeSelection *selection, ITree *it)
199{
200 gtk_tree_selection_select_iter(selection, &it->it);
201}
202
203/**********************************************************************/
206 void itree_unselect(GtkTreeSelection *selection, ITree *it)
207{
208 gtk_tree_selection_unselect_iter(selection, &it->it);
209}
210
211/**********************************************************************/
215 gint gtk_tree_selection_get_row(GtkTreeSelection *selection)
216{
217 GtkTreeModel *model;
218 GtkTreeIter it;
219 gint row = -1;
220
221 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
222 GtkTreePath *path;
223 gint *idx;
224
225 path = gtk_tree_model_get_path(model, &it);
226 idx = gtk_tree_path_get_indices(path);
227 row = idx[0];
228 gtk_tree_path_free(path);
229 }
230 return row;
231}
232
233/**********************************************************************/
236 void gtk_tree_view_focus(GtkTreeView *view)
237{
238 GtkTreeModel *model;
239 GtkTreePath *path;
240 GtkTreeIter iter;
241
242 if ((model = gtk_tree_view_get_model(view))
243 && gtk_tree_model_get_iter_first(model, &iter)
244 && (path = gtk_tree_model_get_path(model, &iter))) {
245 gtk_tree_view_set_cursor(view, path, NULL, FALSE);
246 gtk_tree_path_free(path);
247 gtk_widget_grab_focus(GTK_WIDGET(view));
248 }
249}
250
251/**********************************************************************/
255 GtkWidget *gtk_aux_menu_bar_new(void)
256{
257 GtkWidget *menubar = gtk_menu_bar_new();
258
259 /*
260 * Ubuntu Linux's Ayatana/Unity desktop environment likes to steal the
261 * application's main menu bar from its window and put it at the top of
262 * the screen. It needs a hint in order not to steal menu bars other
263 * than the main one. Gory details at
264 * https://bugs.launchpad.net/ubuntu/+source/freeciv/+bug/743265
265 */
266 if (g_object_class_find_property(
267 G_OBJECT_CLASS(GTK_MENU_BAR_GET_CLASS(menubar)), "ubuntu-local")) {
268 g_object_set(G_OBJECT(menubar), "ubuntu-local", TRUE, NULL);
269 }
270
271 return menubar;
272}
273
274/**********************************************************************/
277 static void close_callback(GtkDialog *dialog, gpointer data)
278{
279 gtk_widget_destroy(GTK_WIDGET(dialog));
280}
281
282/**********************************************************************/
287 void setup_dialog(GtkWidget *shell, GtkWidget *parent)
288{
289 if (GUI_GTK_OPTION(dialogs_on_top) || GUI_GTK_OPTION(fullscreen)) {
290 gtk_window_set_transient_for(GTK_WINDOW(shell),
291 GTK_WINDOW(parent));
292 gtk_window_set_type_hint(GTK_WINDOW(shell),
293 GDK_WINDOW_TYPE_HINT_DIALOG);
294 } else {
295 gtk_window_set_type_hint(GTK_WINDOW(shell),
296 GDK_WINDOW_TYPE_HINT_NORMAL);
297 }
298
299 /* Close dialog window on Escape keypress. */
300 if (GTK_IS_DIALOG(shell)) {
301 g_signal_connect(shell, "focus_out_event",
302 G_CALLBACK(fc_lost_focus), NULL);
303 g_signal_connect(shell, "focus_in_event",
304 G_CALLBACK(fc_gained_focus), NULL);
305 g_signal_connect_after(shell, "close", G_CALLBACK(close_callback), shell);
306 }
307}
308
309/**********************************************************************/
312 static void gui_dialog_response(struct gui_dialog *dlg, int response)
313{
314 if (dlg->response_callback) {
315 (*dlg->response_callback)(dlg, response, dlg->user_data);
316 }
317}
318
319/**********************************************************************/
322 static void gui_dialog_destroyed(struct gui_dialog *dlg, int response,
323 gpointer data)
324{
325 gui_dialog_destroy(dlg);
326}
327
328/**********************************************************************/
331 static void gui_dialog_destroy_handler(GtkWidget *w, struct gui_dialog *dlg)
332{
333 if (dlg->type == GUI_DIALOG_TAB) {
334 GtkWidget *notebook = dlg->v.tab.notebook;
335 gulong handler_id = dlg->v.tab.handler_id;
336
337 g_signal_handler_disconnect(notebook, handler_id);
338 }
339
340 g_object_unref(dlg->gui_button);
341
342 if (*(dlg->source)) {
343 *(dlg->source) = NULL;
344 }
345
346 dialog_list = g_list_remove(dialog_list, dlg);
347
348 /* Raise the return dialog set by gui_dialog_set_return_dialog() */
349 if (dlg->return_dialog_id != -1) {
350 GList *it;
351
352 for (it = dialog_list; it; it = g_list_next(it)) {
353 struct gui_dialog * adialog = (struct gui_dialog *)it->data;
354
355 if (adialog->id == dlg->return_dialog_id) {
356 gui_dialog_raise(adialog);
357 break;
358 }
359 }
360 }
361
362 if (dlg->title) {
363 free(dlg->title);
364 }
365
366 free(dlg);
367}
368
369/**********************************************************************/
374 static gint gui_dialog_delete_handler(GtkWidget *widget,
375 GdkEventAny *ev, gpointer data)
376{
377 struct gui_dialog *dlg = data;
378
379 /* emit response signal. */
380 gui_dialog_response(dlg, GTK_RESPONSE_DELETE_EVENT);
381
382 /* do the destroy by default. */
383 return FALSE;
384}
385
386/**********************************************************************/
391 static gint gui_dialog_delete_tab_handler(struct gui_dialog* dlg)
392{
393 GtkWidget* notebook;
394 int n;
395
396 notebook = dlg->v.tab.notebook;
397 n = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
398 if (gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), n)
399 != dlg->v.tab.child) {
400 gui_dialog_set_return_dialog(dlg, NULL);
401 }
402
403 /* emit response signal. */
404 gui_dialog_response(dlg, GTK_RESPONSE_DELETE_EVENT);
405
406 /* do the destroy by default. */
407 return FALSE;
408}
409
410/**********************************************************************/
413 static gboolean gui_dialog_key_press_handler(GtkWidget *w, GdkEventKey *ev,
414 gpointer data)
415{
416 struct gui_dialog *dlg = data;
417
418 if (ev->keyval == GDK_KEY_Escape
419 || ((ev->state & GDK_CONTROL_MASK) && ev->keyval == GDK_KEY_w)) {
420 /* emit response signal. */
421 gui_dialog_response(dlg, GTK_RESPONSE_DELETE_EVENT);
422 }
423
424 /* propagate event further. */
425 return FALSE;
426}
427
428/**********************************************************************/
431 static void gui_dialog_switch_page_handler(GtkNotebook *notebook,
432 GtkWidget *page,
433 guint num,
434 struct gui_dialog *dlg)
435{
436 gint n;
437
438 n = gtk_notebook_page_num(GTK_NOTEBOOK(dlg->v.tab.notebook), dlg->vbox);
439
440 if (n == num) {
441 GtkStyleContext *context = gtk_widget_get_style_context(dlg->v.tab.label);
442
443 gtk_style_context_remove_class(context, "alert");
444 gtk_style_context_remove_class(context, "notice");
445 }
446}
447
448/**********************************************************************/
451 static void gui_dialog_detach(struct gui_dialog* dlg)
452{
453 gint n;
454 GtkWidget *window, *notebook;
455 gulong handler_id;
456
457 if (dlg->type != GUI_DIALOG_TAB) {
458 return;
459 }
460 dlg->type = GUI_DIALOG_WINDOW;
461
462 /* Create a new reference to the main widget, so it won't be
463 * destroyed in gtk_notebook_remove_page() */
464 g_object_ref(dlg->vbox);
465
466 /* Remove widget from the notebook */
467 notebook = dlg->v.tab.notebook;
468 handler_id = dlg->v.tab.handler_id;
469 g_signal_handler_disconnect(notebook, handler_id);
470
471 n = gtk_notebook_page_num(GTK_NOTEBOOK(dlg->v.tab.notebook), dlg->vbox);
472 gtk_notebook_remove_page(GTK_NOTEBOOK(dlg->v.tab.notebook), n);
473
474
475 /* Create window and put the widget inside */
476 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
477 gtk_window_set_title(GTK_WINDOW(window), dlg->title);
478 setup_dialog(window, toplevel);
479
480 gtk_container_add(GTK_CONTAINER(window), dlg->vbox);
481 dlg->v.window = window;
482 g_signal_connect(window, "delete_event",
483 G_CALLBACK(gui_dialog_delete_handler), dlg);
484
485 gtk_window_set_default_size(GTK_WINDOW(dlg->v.window),
486 dlg->default_width,
487 dlg->default_height);
488 gtk_widget_show_all(window);
489}
490
491/**********************************************************************/
494 static gboolean click_on_tab_callback(GtkWidget *w,
495 GdkEventButton* button,
496 gpointer data)
497{
498 if (button->type != GDK_2BUTTON_PRESS) {
499 return FALSE;
500 }
501 if (button->button != 1) {
502 return FALSE;
503 }
504 gui_dialog_detach((struct gui_dialog*) data);
505 return TRUE;
506}
507
508
509/**********************************************************************/
517 void gui_dialog_new(struct gui_dialog **pdlg, GtkNotebook *notebook,
518 gpointer user_data, bool check_top)
519{
520 struct gui_dialog *dlg;
521 GtkWidget *vbox, *action_area;
522 static int dialog_id_counter;
523
524 dlg = fc_malloc(sizeof(*dlg));
525 dialog_list = g_list_prepend(dialog_list, dlg);
526
527 dlg->source = pdlg;
528 *pdlg = dlg;
529 dlg->user_data = user_data;
530 dlg->title = NULL;
531
532 dlg->default_width = 200;
533 dlg->default_height = 300;
534
535 if (GUI_GTK_OPTION(enable_tabs)) {
536 dlg->type = GUI_DIALOG_TAB;
537 } else {
538 dlg->type = GUI_DIALOG_WINDOW;
539 }
540
541 if (!gui_action) {
542 gui_action = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
543 }
544 dlg->gui_button = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
545
546 vbox = gtk_grid_new();
547 action_area = gtk_grid_new();
548 gtk_grid_set_row_spacing(GTK_GRID(action_area), 4);
549 gtk_grid_set_column_spacing(GTK_GRID(action_area), 4);
550 if (GUI_GTK_OPTION(enable_tabs)
551 && (check_top && notebook != GTK_NOTEBOOK(top_notebook))
552 && !GUI_GTK_OPTION(small_display_layout)) {
553 /* We expect this to be short (as opposed to tall); maximise usable
554 * height by putting buttons down the right hand side */
555 gtk_orientable_set_orientation(GTK_ORIENTABLE(action_area),
556 GTK_ORIENTATION_VERTICAL);
557 } else {
558 /* We expect this to be reasonably tall; maximise usable width by
559 * putting buttons along the bottom */
560 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
561 GTK_ORIENTATION_VERTICAL);
562 }
563
564 gtk_widget_show(vbox);
565 gtk_container_add(GTK_CONTAINER(vbox), action_area);
566 gtk_widget_show(action_area);
567
568 gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
569 gtk_container_set_border_width(GTK_CONTAINER(action_area), 2);
570
571 switch (dlg->type) {
572 case GUI_DIALOG_WINDOW:
573 {
574 GtkWidget *window;
575
576 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
577 gtk_widget_set_name(window, "Freeciv");
578 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
579 setup_dialog(window, toplevel);
580
581 gtk_container_add(GTK_CONTAINER(window), vbox);
582 dlg->v.window = window;
583 g_signal_connect(window, "delete_event",
584 G_CALLBACK(gui_dialog_delete_handler), dlg);
585
586 }
587 break;
588 case GUI_DIALOG_TAB:
589 {
590 GtkWidget *hbox, *label, *image, *button, *event_box;
591 gchar *buf;
592
593 hbox = gtk_grid_new();
594
595 label = gtk_label_new(NULL);
596 gtk_widget_set_halign(label, GTK_ALIGN_START);
597 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
598 gtk_widget_set_margin_start(label, 4);
599 gtk_widget_set_margin_end(label, 4);
600 gtk_widget_set_margin_top(label, 0);
601 gtk_widget_set_margin_bottom(label, 0);
602 gtk_container_add(GTK_CONTAINER(hbox), label);
603
604 button = gtk_button_new();
605 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
606 g_signal_connect_swapped(button, "clicked",
607 G_CALLBACK(gui_dialog_delete_tab_handler), dlg);
608
609 buf = g_strdup_printf(_("Close Tab:\n%s"), _("Ctrl+W"));
610 gtk_widget_set_tooltip_text(button, buf);
611 g_free(buf);
612
613 image = gtk_image_new_from_icon_name("window-close", GTK_ICON_SIZE_MENU);
614 gtk_widget_set_margin_start(image, 0);
615 gtk_widget_set_margin_end(image, 0);
616 gtk_widget_set_margin_top(image, 0);
617 gtk_widget_set_margin_bottom(image, 0);
618 gtk_button_set_image(GTK_BUTTON(button), image);
619
620 gtk_container_add(GTK_CONTAINER(hbox), button);
621
622 gtk_widget_show_all(hbox);
623
624 event_box = gtk_event_box_new();
625 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE);
626 gtk_container_add(GTK_CONTAINER(event_box), hbox);
627
628 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, event_box);
629 dlg->v.tab.handler_id =
630 g_signal_connect(notebook, "switch-page",
631 G_CALLBACK(gui_dialog_switch_page_handler), dlg);
632 dlg->v.tab.child = vbox;
633
634 gtk_style_context_add_provider(gtk_widget_get_style_context(label),
635 GTK_STYLE_PROVIDER(dlg_tab_provider),
636 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
637 dlg->v.tab.label = label;
638 dlg->v.tab.notebook = GTK_WIDGET(notebook);
639
640 gtk_widget_add_events(event_box, GDK_BUTTON2_MOTION_MASK);
641 g_signal_connect(event_box, "button-press-event",
642 G_CALLBACK(click_on_tab_callback), dlg);
643 }
644 break;
645 }
646
647 dlg->vbox = vbox;
648 dlg->action_area = action_area;
649
650 dlg->response_callback = gui_dialog_destroyed;
651
652 dlg->id = dialog_id_counter;
653 dialog_id_counter++;
654 dlg->return_dialog_id = -1;
655
656 g_signal_connect(vbox, "destroy",
657 G_CALLBACK(gui_dialog_destroy_handler), dlg);
658 g_signal_connect(vbox, "key_press_event",
659 G_CALLBACK(gui_dialog_key_press_handler), dlg);
660
661 g_object_set_data(G_OBJECT(vbox), "gui-dialog-data", dlg);
662}
663
664/**********************************************************************/
667 static void action_widget_activated(GtkWidget *button, GtkWidget *vbox)
668{
669 struct gui_dialog *dlg =
670 g_object_get_data(G_OBJECT(vbox), "gui-dialog-data");
671 gpointer arg2 =
672 g_object_get_data(G_OBJECT(button), "gui-dialog-response-data");
673
674 gui_dialog_response(dlg, GPOINTER_TO_INT(arg2));
675}
676
677/**********************************************************************/
680 static void gui_dialog_pack_button(struct gui_dialog *dlg, GtkWidget *button,
681 int response)
682{
683 gint signal_id;
684
685 fc_assert_ret(GTK_IS_BUTTON(button));
686
687 g_object_set_data(G_OBJECT(button), "gui-dialog-response-data",
688 GINT_TO_POINTER(response));
689
690 if ((signal_id = g_signal_lookup("clicked", GTK_TYPE_BUTTON))) {
691 GClosure *closure;
692
693 closure = g_cclosure_new_object(G_CALLBACK(action_widget_activated),
694 G_OBJECT(dlg->vbox));
695 g_signal_connect_closure_by_id(button, signal_id, 0, closure, FALSE);
696 }
697
698 gtk_container_add(GTK_CONTAINER(dlg->action_area), button);
699 gtk_size_group_add_widget(gui_action, button);
700 gtk_size_group_add_widget(dlg->gui_button, button);
701}
702
703/**********************************************************************/
706 GtkWidget *gui_dialog_add_button(struct gui_dialog *dlg,
707 const char *icon_name,
708 const char *text, int response)
709{
710 GtkWidget *button;
711
712 button = icon_label_button_new(icon_name, text);
713 gtk_widget_set_can_default(button, TRUE);
714 gui_dialog_pack_button(dlg, button, response);
715
716 return button;
717}
718
719/**********************************************************************/
722 GtkWidget *gui_dialog_add_widget(struct gui_dialog *dlg,
723 GtkWidget *widget)
724{
725 gtk_container_add(GTK_CONTAINER(dlg->action_area), widget);
726 gtk_size_group_add_widget(gui_action, widget);
727
728 return widget;
729}
730
731/**********************************************************************/
734 void gui_dialog_set_default_response(struct gui_dialog *dlg, int response)
735{
736 GList *children;
737 GList *list;
738
739 children = gtk_container_get_children(GTK_CONTAINER(dlg->action_area));
740
741 for (list = children; list; list = g_list_next(list)) {
742 GtkWidget *button = list->data;
743
744 if (GTK_IS_BUTTON(button)) {
745 gpointer data = g_object_get_data(G_OBJECT(button),
746 "gui-dialog-response-data");
747
748 if (response == GPOINTER_TO_INT(data)) {
749 gtk_widget_grab_default(button);
750 }
751 }
752 }
753
754 g_list_free(children);
755}
756
757/**********************************************************************/
760 void gui_dialog_set_response_sensitive(struct gui_dialog *dlg,
761 int response, bool setting)
762{
763 GList *children;
764 GList *list;
765
766 children = gtk_container_get_children(GTK_CONTAINER(dlg->action_area));
767
768 for (list = children; list; list = g_list_next(list)) {
769 GtkWidget *button = list->data;
770
771 if (GTK_IS_BUTTON(button)) {
772 gpointer data = g_object_get_data(G_OBJECT(button),
773 "gui-dialog-response-data");
774
775 if (response == GPOINTER_TO_INT(data)) {
776 gtk_widget_set_sensitive(button, setting);
777 }
778 }
779 }
780
781 g_list_free(children);
782}
783
784/**********************************************************************/
787 GtkWidget *gui_dialog_get_toplevel(struct gui_dialog *dlg)
788{
789 return gtk_widget_get_toplevel(dlg->vbox);
790}
791
792/**********************************************************************/
795 void gui_dialog_show_all(struct gui_dialog *dlg)
796{
797 gtk_widget_show_all(dlg->vbox);
798
799 if (dlg->type == GUI_DIALOG_TAB) {
800 GList *children;
801 GList *list;
802 gint num_visible = 0;
803
804 children = gtk_container_get_children(GTK_CONTAINER(dlg->action_area));
805
806 for (list = children; list; list = g_list_next(list)) {
807 GtkWidget *button = list->data;
808
809 if (!GTK_IS_BUTTON(button)) {
810 num_visible++;
811 } else {
812 gpointer data = g_object_get_data(G_OBJECT(button),
813 "gui-dialog-response-data");
814 int response = GPOINTER_TO_INT(data);
815
816 if (response != GTK_RESPONSE_CLOSE
817 && response != GTK_RESPONSE_CANCEL) {
818 num_visible++;
819 } else {
820 gtk_widget_hide(button);
821 }
822 }
823 }
824 g_list_free(children);
825
826 if (num_visible == 0) {
827 gtk_widget_hide(dlg->action_area);
828 }
829 }
830}
831
832/**********************************************************************/
835 void gui_dialog_present(struct gui_dialog *dlg)
836{
837 fc_assert_ret(NULL != dlg);
838
839 switch (dlg->type) {
840 case GUI_DIALOG_WINDOW:
841 gtk_widget_show(dlg->v.window);
842 break;
843 case GUI_DIALOG_TAB:
844 {
845 GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
846 gint current, n;
847
848 current = gtk_notebook_get_current_page(notebook);
849 n = gtk_notebook_page_num(notebook, dlg->vbox);
850
851 if (current != n) {
852 GtkWidget *label = dlg->v.tab.label;
853
854 gtk_style_context_add_class(gtk_widget_get_style_context(label),
855 "notice");
856 }
857 }
858 break;
859 }
860}
861
862/**********************************************************************/
865 void gui_dialog_raise(struct gui_dialog *dlg)
866{
867 fc_assert_ret(NULL != dlg);
868
869 switch (dlg->type) {
870 case GUI_DIALOG_WINDOW:
871 gtk_window_present(GTK_WINDOW(dlg->v.window));
872 break;
873 case GUI_DIALOG_TAB:
874 {
875 GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
876 gint n;
877
878 n = gtk_notebook_page_num(notebook, dlg->vbox);
879 gtk_notebook_set_current_page(notebook, n);
880 }
881 break;
882 }
883}
884
885/**********************************************************************/
888 void gui_dialog_alert(struct gui_dialog *dlg)
889{
890 fc_assert_ret(NULL != dlg);
891
892 switch (dlg->type) {
893 case GUI_DIALOG_WINDOW:
894 break;
895 case GUI_DIALOG_TAB:
896 {
897 GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
898 gint current, n;
899
900 current = gtk_notebook_get_current_page(notebook);
901 n = gtk_notebook_page_num(notebook, dlg->vbox);
902
903 if (current != n) {
904 GtkWidget *label = dlg->v.tab.label;
905 GtkStyleContext *context = gtk_widget_get_style_context(label);
906
907 /* Have only alert - remove notice if it exist. */
908 gtk_style_context_remove_class(context, "notice");
909 gtk_style_context_add_class(context, "alert");
910 }
911 }
912 break;
913 }
914}
915
916/**********************************************************************/
919 void gui_dialog_set_default_size(struct gui_dialog *dlg, int width, int height)
920{
921 dlg->default_width = width;
922 dlg->default_height = height;
923 switch (dlg->type) {
924 case GUI_DIALOG_WINDOW:
925 gtk_window_set_default_size(GTK_WINDOW(dlg->v.window), width, height);
926 break;
927 case GUI_DIALOG_TAB:
928 break;
929 }
930}
931
932/**********************************************************************/
935 void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
936{
937 if (dlg->title) {
938 free(dlg->title);
939 }
940 dlg->title = fc_strdup(title);
941 switch (dlg->type) {
942 case GUI_DIALOG_WINDOW:
943 gtk_window_set_title(GTK_WINDOW(dlg->v.window), title);
944 break;
945 case GUI_DIALOG_TAB:
946 gtk_label_set_text_with_mnemonic(GTK_LABEL(dlg->v.tab.label), title);
947 break;
948 }
949}
950
951/**********************************************************************/
954 void gui_dialog_destroy(struct gui_dialog *dlg)
955{
956 switch (dlg->type) {
957 case GUI_DIALOG_WINDOW:
958 gtk_widget_destroy(dlg->v.window);
959 break;
960 case GUI_DIALOG_TAB:
961 {
962 gint n;
963
964 n = gtk_notebook_page_num(GTK_NOTEBOOK(dlg->v.tab.notebook), dlg->vbox);
965 gtk_notebook_remove_page(GTK_NOTEBOOK(dlg->v.tab.notebook), n);
966 }
967 break;
968 }
969}
970
971/**********************************************************************/
974 void gui_dialog_destroy_all(void)
975{
976 GList *it, *it_next;
977
978 for (it = dialog_list; it; it = it_next) {
979 it_next = g_list_next(it);
980
981 gui_dialog_destroy((struct gui_dialog *)it->data);
982 }
983}
984
985/**********************************************************************/
988 void gui_dialog_response_set_callback(struct gui_dialog *dlg,
989 GUI_DIALOG_RESPONSE_FUN fun)
990{
991 dlg->response_callback = fun;
992}
993
994/**********************************************************************/
997 void gui_dialog_set_return_dialog(struct gui_dialog *dlg,
998 struct gui_dialog *return_dialog)
999{
1000 if (return_dialog == NULL) {
1001 dlg->return_dialog_id = -1;
1002 } else {
1003 dlg->return_dialog_id = return_dialog->id;
1004 }
1005}
1006
1007/**********************************************************************/
1010 void gui_update_font(const char *font_name, const char *font_value)
1011{
1012 char *str;
1013 GtkCssProvider *provider;
1014 PangoFontDescription *desc;
1015 int size;
1016 const char *fam;
1017 const char *style;
1018 const char *weight;
1019
1020 desc = pango_font_description_from_string(font_value);
1021
1022 if (desc == NULL) {
1023 return;
1024 }
1025
1026 fam = pango_font_description_get_family(desc);
1027
1028 if (fam == NULL) {
1029 return;
1030 }
1031
1032 if (pango_font_description_get_style(desc) == PANGO_STYLE_ITALIC) {
1033 style = "\n font-style: italic;";
1034 } else {
1035 style = "";
1036 }
1037
1038 if (pango_font_description_get_weight(desc) >= 700) {
1039 weight = "\n font-weight: bold;";
1040 } else {
1041 weight = "";
1042 }
1043
1044 size = pango_font_description_get_size(desc);
1045
1046 if (size != 0) {
1047 if (pango_font_description_get_size_is_absolute(desc)) {
1048 str = g_strdup_printf("#Freeciv #%s { font-family: %s; font-size: %dpx;%s%s}",
1049 font_name, fam, size / PANGO_SCALE, style, weight);
1050 } else {
1051 str = g_strdup_printf("#Freeciv #%s { font-family: %s; font-size: %dpt;%s%s}",
1052 font_name, fam, size / PANGO_SCALE, style, weight);
1053 }
1054 } else {
1055 str = g_strdup_printf("#Freeciv #%s { font-family: %s;%s%s}",
1056 font_name, fam, style, weight);
1057 }
1058
1059 pango_font_description_free(desc);
1060
1061 provider = gtk_css_provider_new();
1062 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
1063 str, -1, NULL);
1064 gtk_style_context_add_provider_for_screen(
1065 gtk_widget_get_screen(toplevel), GTK_STYLE_PROVIDER(provider),
1066 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1067 g_free(str);
1068}
1069
1070/**********************************************************************/
1073 void gui_update_font_full(const char *font_name, const char *font_value,
1074 PangoFontDescription **font_desc)
1075{
1076 PangoFontDescription *f_desc;
1077
1078 gui_update_font(font_name, font_value);
1079
1080 f_desc = pango_font_description_from_string(font_value);
1081 pango_font_description_free(*font_desc);
1082
1083 *font_desc = f_desc;
1084}
1085
1086/**********************************************************************/
1090 void disable_gobject_callback(GObject *obj, GCallback cb)
1091{
1092 gulong hid;
1093
1094 if (!obj || !cb) {
1095 return;
1096 }
1097
1098 hid = g_signal_handler_find(obj, G_SIGNAL_MATCH_FUNC,
1099 0, 0, NULL, cb, NULL);
1100 g_signal_handler_block(obj, hid);
1101}
1102
1103/**********************************************************************/
1106 void enable_gobject_callback(GObject *obj, GCallback cb)
1107{
1108 gulong hid;
1109
1110 if (!obj || !cb) {
1111 return;
1112 }
1113
1114 hid = g_signal_handler_find(obj, G_SIGNAL_MATCH_FUNC,
1115 0, 0, NULL, cb, NULL);
1116 g_signal_handler_unblock(obj, hid);
1117}
1118
1119/**********************************************************************/
1123 GtkTreeViewColumn *add_treeview_column(GtkWidget *view, const char *title,
1124 GType gtype, int model_index)
1125{
1126 GtkTreeViewColumn *col;
1127 GtkCellRenderer *rend;
1128 const char *attr;
1129
1130 fc_assert_ret_val(view != NULL, NULL);
1131 fc_assert_ret_val(GTK_IS_TREE_VIEW(view), NULL);
1132 fc_assert_ret_val(title != NULL, NULL);
1133
1134 if (gtype == G_TYPE_BOOLEAN) {
1135 rend = gtk_cell_renderer_toggle_new();
1136 attr = "active";
1137 } else if (gtype == GDK_TYPE_PIXBUF) {
1138 rend = gtk_cell_renderer_pixbuf_new();
1139 attr = "pixbuf";
1140 } else {
1141 rend = gtk_cell_renderer_text_new();
1142 attr = "text";
1143 }
1144
1145 col = gtk_tree_view_column_new_with_attributes(title, rend, attr,
1146 model_index, NULL);
1147 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
1148
1149 return col;
1150}
1151
1152/**********************************************************************/
1155 void dlg_tab_provider_prepare(void)
1156{
1157 dlg_tab_provider = gtk_css_provider_new();
1158
1159 gtk_css_provider_load_from_data(dlg_tab_provider,
1160 ".alert {\n"
1161 "color: rgba(255, 0, 0, 255);\n"
1162 "}\n"
1163 ".notice {\n"
1164 "color: rgba(0, 0, 255, 255);\n"
1165 "}\n",
1166 -1, NULL);
1167}
str
#define str
Definition astring.c:76
n
#define n
Definition astring.c:77
height
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
width
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
list
static struct fc_sockaddr_list * list
Definition clinet.c:102
incite_cost
char * incite_cost
Definition comments.c:74
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
_
#define _(String)
Definition fcintl.h:67
top_notebook
GtkWidget * top_notebook
Definition gui_main.c:129
fc_lost_focus
gboolean fc_lost_focus(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:758
fc_gained_focus
gboolean fc_gained_focus(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:768
toplevel
GtkWidget * toplevel
Definition gui_main.c:125
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
gtk_tree_view_focus
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:236
gui_dialog_destroy
void gui_dialog_destroy(struct gui_dialog *dlg)
Definition gui_stuff.c:954
gui_dialog_pack_button
static void gui_dialog_pack_button(struct gui_dialog *dlg, GtkWidget *button, int response)
Definition gui_stuff.c:680
gui_dialog_present
void gui_dialog_present(struct gui_dialog *dlg)
Definition gui_stuff.c:835
gui_dialog_switch_page_handler
static void gui_dialog_switch_page_handler(GtkNotebook *notebook, GtkWidget *page, guint num, struct gui_dialog *dlg)
Definition gui_stuff.c:431
gtk_stockbutton_set_label
void gtk_stockbutton_set_label(GtkWidget *button, const gchar *label_text)
Definition gui_stuff.c:96
gui_dialog_set_default_response
void gui_dialog_set_default_response(struct gui_dialog *dlg, int response)
Definition gui_stuff.c:734
dlg_tab_provider
static GtkCssProvider * dlg_tab_provider
Definition gui_stuff.c:46
itree_get
void itree_get(ITree *it,...)
Definition gui_stuff.c:164
itree_set
void itree_set(ITree *it,...)
Definition gui_stuff.c:152
gui_dialog_raise
void gui_dialog_raise(struct gui_dialog *dlg)
Definition gui_stuff.c:865
gui_dialog_new
void gui_dialog_new(struct gui_dialog **pdlg, GtkNotebook *notebook, gpointer user_data, bool check_top)
Definition gui_stuff.c:517
disable_gobject_callback
void disable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1090
gui_dialog_add_widget
GtkWidget * gui_dialog_add_widget(struct gui_dialog *dlg, GtkWidget *widget)
Definition gui_stuff.c:722
gtk_tree_selection_get_row
gint gtk_tree_selection_get_row(GtkTreeSelection *selection)
Definition gui_stuff.c:215
gui_dialog_set_return_dialog
void gui_dialog_set_return_dialog(struct gui_dialog *dlg, struct gui_dialog *return_dialog)
Definition gui_stuff.c:997
dlg_tab_provider_prepare
void dlg_tab_provider_prepare(void)
Definition gui_stuff.c:1155
set_relative_window_position
void set_relative_window_position(GtkWindow *ref, GtkWindow *w, int px, int py)
Definition gui_stuff.c:60
gui_dialog_response_set_callback
void gui_dialog_response_set_callback(struct gui_dialog *dlg, GUI_DIALOG_RESPONSE_FUN fun)
Definition gui_stuff.c:988
gui_action
static GtkSizeGroup * gui_action
Definition gui_stuff.c:44
itree_begin
void itree_begin(GtkTreeModel *model, ITree *it)
Definition gui_stuff.c:127
gui_dialog_destroyed
static void gui_dialog_destroyed(struct gui_dialog *dlg, int response, gpointer data)
Definition gui_stuff.c:322
action_widget_activated
static void action_widget_activated(GtkWidget *button, GtkWidget *vbox)
Definition gui_stuff.c:667
itree_unselect
void itree_unselect(GtkTreeSelection *selection, ITree *it)
Definition gui_stuff.c:206
enable_gobject_callback
void enable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1106
gui_dialog_detach
static void gui_dialog_detach(struct gui_dialog *dlg)
Definition gui_stuff.c:451
gui_dialog_show_all
void gui_dialog_show_all(struct gui_dialog *dlg)
Definition gui_stuff.c:795
gui_dialog_key_press_handler
static gboolean gui_dialog_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_stuff.c:413
gui_dialog_delete_handler
static gint gui_dialog_delete_handler(GtkWidget *widget, GdkEventAny *ev, gpointer data)
Definition gui_stuff.c:374
itree_select
void itree_select(GtkTreeSelection *selection, ITree *it)
Definition gui_stuff.c:198
gui_dialog_set_title
void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
Definition gui_stuff.c:935
close_callback
static void close_callback(GtkDialog *dialog, gpointer data)
Definition gui_stuff.c:277
gui_dialog_set_default_size
void gui_dialog_set_default_size(struct gui_dialog *dlg, int width, int height)
Definition gui_stuff.c:919
icon_label_button_new
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
gui_dialog_alert
void gui_dialog_alert(struct gui_dialog *dlg)
Definition gui_stuff.c:888
add_treeview_column
GtkTreeViewColumn * add_treeview_column(GtkWidget *view, const char *title, GType gtype, int model_index)
Definition gui_stuff.c:1123
gui_dialog_destroy_handler
static void gui_dialog_destroy_handler(GtkWidget *w, struct gui_dialog *dlg)
Definition gui_stuff.c:331
tstore_append
void tstore_append(GtkTreeStore *store, ITree *it, ITree *parent)
Definition gui_stuff.c:176
gui_dialog_delete_tab_handler
static gint gui_dialog_delete_tab_handler(struct gui_dialog *dlg)
Definition gui_stuff.c:391
itree_next
void itree_next(ITree *it)
Definition gui_stuff.c:144
gui_dialog_destroy_all
void gui_dialog_destroy_all(void)
Definition gui_stuff.c:974
click_on_tab_callback
static gboolean click_on_tab_callback(GtkWidget *w, GdkEventButton *button, gpointer data)
Definition gui_stuff.c:494
itree_is_selected
gboolean itree_is_selected(GtkTreeSelection *selection, ITree *it)
Definition gui_stuff.c:190
gtk_aux_menu_bar_new
GtkWidget * gtk_aux_menu_bar_new(void)
Definition gui_stuff.c:255
gui_dialog_add_button
GtkWidget * gui_dialog_add_button(struct gui_dialog *dlg, const char *icon_name, const char *text, int response)
Definition gui_stuff.c:706
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
dialog_list
static GList * dialog_list
Definition gui_stuff.c:42
gui_update_font_full
void gui_update_font_full(const char *font_name, const char *font_value, PangoFontDescription **font_desc)
Definition gui_stuff.c:1073
gtk_expose_now
void gtk_expose_now(GtkWidget *w)
Definition gui_stuff.c:52
gui_dialog_set_response_sensitive
void gui_dialog_set_response_sensitive(struct gui_dialog *dlg, int response, bool setting)
Definition gui_stuff.c:760
gui_dialog_get_toplevel
GtkWidget * gui_dialog_get_toplevel(struct gui_dialog *dlg)
Definition gui_stuff.c:787
intl_slist
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:111
itree_end
gboolean itree_end(ITree *it)
Definition gui_stuff.c:136
gui_dialog_response
static void gui_dialog_response(struct gui_dialog *dlg, int response)
Definition gui_stuff.c:312
GUI_DIALOG_WINDOW
@ GUI_DIALOG_WINDOW
Definition gui_stuff.h:61
GUI_DIALOG_TAB
@ GUI_DIALOG_TAB
Definition gui_stuff.h:62
GUI_DIALOG_RESPONSE_FUN
void(* GUI_DIALOG_RESPONSE_FUN)(struct gui_dialog *, int, gpointer)
Definition gui_stuff.h:67
shell
static struct gui_dialog * shell
Definition messagedlg.c:39
title
const char * title
Definition repodlgs.c:1314
gui_stuff.h
colors.h
gui_main.h
font_name
const char * font_name
Definition gui_main_g.h:43
gui_update_font
gui_update_font
Definition gui_main_g.h:43
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
mem.h
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
options.h
size
size_t size
Definition specvec.h:72
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
ITree
Definition gui_stuff.h:32
ITree::model
GtkTreeModel * model
Definition gui_stuff.h:33
ITree::end
gboolean end
Definition gui_stuff.h:34
ITree::it
GtkTreeIter it
Definition gui_stuff.h:35
gui_dialog
Definition gui_stuff.h:70
gui_dialog::vbox
GtkWidget * vbox
Definition gui_stuff.h:72
gui_dialog::title
char * title
Definition gui_stuff.h:76
gui_dialog::handler_id
gulong handler_id
Definition gui_stuff.h:89
gui_dialog::id
int id
Definition gui_stuff.h:78
gui_dialog::gui_button
GtkSizeGroup * gui_button
Definition gui_stuff.h:99
gui_dialog::action_area
GtkWidget * action_area
Definition gui_stuff.h:73
gui_dialog::response_callback
GUI_DIALOG_RESPONSE_FUN response_callback
Definition gui_stuff.h:96
gui_dialog::tab
struct gui_dialog::@151::@152 tab
gui_dialog::label
GtkWidget * label
Definition gui_stuff.h:87
gui_dialog::notebook
GtkWidget * notebook
Definition gui_stuff.h:88
gui_dialog::return_dialog_id
int return_dialog_id
Definition gui_stuff.h:79
gui_dialog::default_height
int default_height
Definition gui_stuff.h:82
gui_dialog::source
struct gui_dialog ** source
Definition gui_stuff.h:94
gui_dialog::user_data
gpointer user_data
Definition gui_stuff.h:97
gui_dialog::v
union gui_dialog::@151 v
gui_dialog::window
GtkWidget * window
Definition gui_stuff.h:85
gui_dialog::type
enum gui_dialog_type type
Definition gui_stuff.h:77
gui_dialog::default_width
int default_width
Definition gui_stuff.h:81
gui_dialog::child
GtkWidget * child
Definition gui_stuff.h:90
setting
Definition settings.c:92
view
Definition mapview_common.h:36
widget
Definition widget.h:112
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47