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