Qt client - remove right click menu from end turn sidebar
[freeciv.git] / client / gui-gtk-3.0 / optiondlg.c
blob34ecc0a3624a54a4db0a0849e0ea3b31ac094c67
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdlib.h>
20 #include <gtk/gtk.h>
22 /* utility */
23 #include "log.h"
24 #include "mem.h"
25 #include "string_vector.h"
27 /* client */
28 #include "options.h"
30 /* client/gui-gtk-3.0 */
31 #include "colors.h"
32 #include "dialogs.h"
33 #include "gui_main.h"
34 #include "gui_stuff.h"
35 #include "pages.h"
37 #include "optiondlg.h"
40 /* The option dialog data. */
41 struct option_dialog {
42 const struct option_set *poptset; /* The option set. */
43 GtkWidget *shell; /* The main widget. */
44 GtkWidget *notebook; /* The notebook. */
45 GtkWidget **vboxes; /* Category boxes. */
46 int *box_children; /* The number of children for
47 * each category. */
50 #define SPECLIST_TAG option_dialog
51 #define SPECLIST_TYPE struct option_dialog
52 #include "speclist.h"
53 #define option_dialogs_iterate(pdialog) \
54 TYPED_LIST_ITERATE(struct option_dialog, option_dialogs, pdialog)
55 #define option_dialogs_iterate_end LIST_ITERATE_END
57 /* All option dialog are set on this list. */
58 static struct option_dialog_list *option_dialogs = NULL;
60 enum {
61 RESPONSE_CANCEL,
62 RESPONSE_OK,
63 RESPONSE_APPLY,
64 RESPONSE_RESET,
65 RESPONSE_REFRESH,
66 RESPONSE_SAVE
70 /* Option dialog main functions. */
71 static struct option_dialog *
72 option_dialog_get(const struct option_set *poptset);
73 static struct option_dialog *
74 option_dialog_new(const char *name, const struct option_set *poptset);
75 static void option_dialog_destroy(struct option_dialog *pdialog);
77 static void option_dialog_reorder_notebook(struct option_dialog *pdialog);
78 static inline void option_dialog_foreach(struct option_dialog *pdialog,
79 void (*option_action)
80 (struct option *));
82 /* Option dialog option-specific functions. */
83 static void option_dialog_option_add(struct option_dialog *pdialog,
84 struct option *poption,
85 bool reorder_notebook);
86 static void option_dialog_option_remove(struct option_dialog *pdialog,
87 struct option *poption);
89 static void option_dialog_option_refresh(struct option *poption);
90 static void option_dialog_option_reset(struct option *poption);
91 static void option_dialog_option_apply(struct option *poption);
94 /****************************************************************************
95 Option dialog widget response callback.
96 ****************************************************************************/
97 static void option_dialog_reponse_callback(GtkDialog *dialog,
98 gint response_id, gpointer data)
100 struct option_dialog *pdialog = (struct option_dialog *) data;
102 switch (response_id) {
103 case RESPONSE_CANCEL:
104 gtk_widget_destroy(GTK_WIDGET(dialog));
105 break;
106 case RESPONSE_OK:
107 option_dialog_foreach(pdialog, option_dialog_option_apply);
108 gtk_widget_destroy(GTK_WIDGET(dialog));
109 break;
110 case RESPONSE_APPLY:
111 option_dialog_foreach(pdialog, option_dialog_option_apply);
112 break;
113 case RESPONSE_RESET:
114 option_dialog_foreach(pdialog, option_dialog_option_reset);
115 break;
116 case RESPONSE_REFRESH:
117 option_dialog_foreach(pdialog, option_dialog_option_refresh);
118 break;
119 case RESPONSE_SAVE:
120 desired_settable_options_update();
121 options_save(NULL);
122 break;
126 /****************************************************************************
127 Option dialog widget destroyed callback.
128 ****************************************************************************/
129 static void option_dialog_destroy_callback(GtkWidget *object, gpointer data)
131 struct option_dialog *pdialog = (struct option_dialog *) data;
133 if (NULL != pdialog->shell) {
134 /* Mark as destroyed, see also option_dialog_destroy(). */
135 pdialog->shell = NULL;
136 option_dialog_destroy(pdialog);
140 /*************************************************************************
141 Option refresh requested from menu.
142 *************************************************************************/
143 static void option_refresh_callback(GtkMenuItem *menuitem, gpointer data)
145 struct option *poption = (struct option *) data;
146 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
148 if (NULL != pdialog) {
149 option_dialog_option_refresh(poption);
153 /*************************************************************************
154 Option reset requested from menu.
155 *************************************************************************/
156 static void option_reset_callback(GtkMenuItem *menuitem, gpointer data)
158 struct option *poption = (struct option *) data;
159 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
161 if (NULL != pdialog) {
162 option_dialog_option_reset(poption);
166 /*************************************************************************
167 Option apply requested from menu.
168 *************************************************************************/
169 static void option_apply_callback(GtkMenuItem *menuitem, gpointer data)
171 struct option *poption = (struct option *) data;
172 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
174 if (NULL != pdialog) {
175 option_dialog_option_apply(poption);
179 /*************************************************************************
180 Called when a button is pressed on a option.
181 *************************************************************************/
182 static gboolean option_button_press_callback(GtkWidget *widget,
183 GdkEventButton *event,
184 gpointer data)
186 struct option *poption = (struct option *) data;
187 GtkWidget *menu, *item;
189 if (3 != event->button || !option_is_changeable(poption)) {
190 /* Only right button please! */
191 return FALSE;
194 menu = gtk_menu_new();
196 item = gtk_image_menu_item_new_with_label(_("Refresh this option"));
197 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
198 gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU));
199 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
200 g_signal_connect(item, "activate",
201 G_CALLBACK(option_refresh_callback), poption);
203 item = gtk_image_menu_item_new_with_label(_("Reset this option"));
204 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
205 gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU));
206 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
207 g_signal_connect(item, "activate",
208 G_CALLBACK(option_reset_callback), poption);
210 item = gtk_image_menu_item_new_with_label(
211 _("Apply the changes for this option"));
212 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
213 gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU));
214 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
215 g_signal_connect(item, "activate",
216 G_CALLBACK(option_apply_callback), poption);
218 gtk_widget_show_all(menu);
219 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
221 return TRUE;
224 /****************************************************************************
225 Returns the option dialog which fit the option set.
226 ****************************************************************************/
227 static struct option_dialog *
228 option_dialog_get(const struct option_set *poptset)
230 if (NULL != option_dialogs) {
231 option_dialogs_iterate(pdialog) {
232 if (pdialog->poptset == poptset) {
233 return pdialog;
235 } option_dialogs_iterate_end;
237 return NULL;
240 /****************************************************************************
241 GDestroyNotify callback.
242 ****************************************************************************/
243 static void option_color_destroy_notify(gpointer data)
245 GdkRGBA *color = (GdkRGBA *) data;
247 if (NULL != color) {
248 gdk_rgba_free(color);
252 /****************************************************************************
253 Set the color of a button.
254 ****************************************************************************/
255 static void option_color_set_button_color(GtkButton *button,
256 const GdkRGBA *new_color)
258 GdkRGBA *current_color = g_object_get_data(G_OBJECT(button), "color");
259 GtkWidget *child;
261 if (NULL == new_color) {
262 if (NULL != current_color) {
263 g_object_set_data(G_OBJECT(button), "color", NULL);
264 if ((child = gtk_bin_get_child(GTK_BIN(button)))) {
265 gtk_widget_destroy(child);
268 } else {
269 GdkPixbuf *pixbuf;
271 /* Apply the new color. */
272 if (NULL != current_color) {
273 /* We already have a GdkRGBA pointer. */
274 *current_color = *new_color;
275 } else {
276 /* We need to make a GdkRGBA pointer. */
277 current_color = gdk_rgba_copy(new_color);
278 g_object_set_data_full(G_OBJECT(button), "color", current_color,
279 option_color_destroy_notify);
281 if ((child = gtk_bin_get_child(GTK_BIN(button)))) {
282 gtk_widget_destroy(child);
285 /* Update the button. */
287 cairo_surface_t *surface = cairo_image_surface_create(
288 CAIRO_FORMAT_RGB24, 16, 16);
289 cairo_t *cr = cairo_create(surface);
290 gdk_cairo_set_source_rgba(cr, current_color);
291 cairo_paint(cr);
292 cairo_destroy(cr);
293 pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, 16, 16);
294 cairo_surface_destroy(surface);
296 child = gtk_image_new_from_pixbuf(pixbuf);
297 gtk_container_add(GTK_CONTAINER(button), child);
298 gtk_widget_show(child);
299 g_object_unref(G_OBJECT(pixbuf));
303 /****************************************************************************
304 "response" signal callback.
305 ****************************************************************************/
306 static void color_selector_response_callback(GtkDialog *dialog,
307 gint res, gpointer data)
309 if (res == GTK_RESPONSE_REJECT) {
310 /* Clears the current color. */
311 option_color_set_button_color(GTK_BUTTON(data), NULL);
312 } else if (res == GTK_RESPONSE_OK) {
313 /* Apply the new color. */
314 GtkColorChooser *chooser =
315 GTK_COLOR_CHOOSER(g_object_get_data(G_OBJECT(dialog), "chooser"));
316 GdkRGBA new_color;
318 gtk_color_chooser_get_rgba(chooser, &new_color);
319 option_color_set_button_color(GTK_BUTTON(data), &new_color);
322 gtk_widget_destroy(GTK_WIDGET(dialog));
325 /****************************************************************************
326 Called when the user press a color button.
327 ****************************************************************************/
328 static void option_color_select_callback(GtkButton *button, gpointer data)
330 GtkWidget *dialog, *chooser;
331 GdkRGBA *current_color = g_object_get_data(G_OBJECT(button), "color");
333 dialog = gtk_dialog_new_with_buttons(_("Select a color"), NULL,
334 GTK_DIALOG_MODAL,
335 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
336 GTK_STOCK_CLEAR, GTK_RESPONSE_REJECT,
337 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
338 setup_dialog(dialog, toplevel);
339 g_signal_connect(dialog, "response",
340 G_CALLBACK(color_selector_response_callback), button);
342 chooser = gtk_color_chooser_widget_new();
343 g_object_set_data(G_OBJECT(dialog), "chooser", chooser);
344 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), chooser,
345 FALSE, FALSE, 0);
346 if (current_color) {
347 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(chooser), current_color);
350 gtk_widget_show_all(dialog);
354 /****************************************************************************
355 Creates a new option dialog.
356 ****************************************************************************/
357 static struct option_dialog *
358 option_dialog_new(const char *name, const struct option_set *poptset)
360 struct option_dialog *pdialog;
361 const int CATEGORY_NUM = optset_category_number(poptset);
363 /* Create the dialog structure. */
364 pdialog = fc_malloc(sizeof(*pdialog));
365 pdialog->poptset = poptset;
366 pdialog->shell = gtk_dialog_new_with_buttons(name, NULL, 0,
367 GTK_STOCK_CANCEL, RESPONSE_CANCEL,
368 GTK_STOCK_SAVE, RESPONSE_SAVE,
369 GTK_STOCK_REFRESH, RESPONSE_REFRESH,
370 _("Reset"), RESPONSE_RESET,
371 GTK_STOCK_APPLY, RESPONSE_APPLY,
372 GTK_STOCK_OK, RESPONSE_OK, NULL);
373 pdialog->notebook = gtk_notebook_new();
374 pdialog->vboxes = fc_calloc(CATEGORY_NUM, sizeof(*pdialog->vboxes));
375 pdialog->box_children = fc_calloc(CATEGORY_NUM,
376 sizeof(*pdialog->box_children));
378 /* Append to the option dialog list. */
379 if (NULL == option_dialogs) {
380 option_dialogs = option_dialog_list_new();
382 option_dialog_list_append(option_dialogs, pdialog);
384 /* Shell */
385 setup_dialog(pdialog->shell, toplevel);
386 gtk_window_set_position(GTK_WINDOW(pdialog->shell), GTK_WIN_POS_MOUSE);
387 gtk_window_set_default_size(GTK_WINDOW(pdialog->shell), -1, 480);
388 g_signal_connect(pdialog->shell, "response",
389 G_CALLBACK(option_dialog_reponse_callback), pdialog);
390 g_signal_connect(pdialog->shell, "destroy",
391 G_CALLBACK(option_dialog_destroy_callback), pdialog);
393 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(pdialog->shell))),
394 pdialog->notebook, TRUE, TRUE, 0);
396 /* Add the options. */
397 options_iterate(poptset, poption) {
398 option_dialog_option_add(pdialog, poption, FALSE);
399 } options_iterate_end;
401 option_dialog_reorder_notebook(pdialog);
403 /* Show the widgets. */
404 gtk_widget_show_all(pdialog->shell);
406 return pdialog;
409 /****************************************************************************
410 Destroys an option dialog.
411 ****************************************************************************/
412 static void option_dialog_destroy(struct option_dialog *pdialog)
414 GtkWidget *shell = pdialog->shell;
416 if (NULL != option_dialogs) {
417 option_dialog_list_remove(option_dialogs, pdialog);
420 options_iterate(pdialog->poptset, poption) {
421 option_set_gui_data(poption, NULL);
422 } options_iterate_end;
424 if (NULL != shell) {
425 /* Maybe already destroyed, see also option_dialog_destroy_callback(). */
426 pdialog->shell = NULL;
427 gtk_widget_destroy(shell);
430 free(pdialog->vboxes);
431 free(pdialog->box_children);
432 free(pdialog);
435 /****************************************************************************
436 Utility for sorting the pages of a option dialog.
437 ****************************************************************************/
438 static int option_dialog_pages_sort_func(const void *w1, const void *w2)
440 GObject *obj1 = G_OBJECT(*(GtkWidget **) w1);
441 GObject *obj2 = G_OBJECT(*(GtkWidget **) w2);
443 return (GPOINTER_TO_INT(g_object_get_data(obj1, "category"))
444 - GPOINTER_TO_INT(g_object_get_data(obj2, "category")));
447 /****************************************************************************
448 Reoder the pages of the notebook of the option dialog.
449 ****************************************************************************/
450 static void option_dialog_reorder_notebook(struct option_dialog *pdialog)
452 GtkNotebook *notebook = GTK_NOTEBOOK(pdialog->notebook);
453 const int pages_num = gtk_notebook_get_n_pages(notebook);
455 if (0 < pages_num) {
456 GtkWidget *pages[pages_num];
457 int i;
459 for (i = 0; i < pages_num; i++) {
460 pages[i] = gtk_notebook_get_nth_page(notebook, i);
462 qsort(pages, pages_num, sizeof(*pages), option_dialog_pages_sort_func);
463 for (i = 0; i < pages_num; i++) {
464 gtk_notebook_reorder_child(notebook, pages[i], i);
469 /****************************************************************************
470 Do an action for all options of the option dialog.
471 ****************************************************************************/
472 static inline void option_dialog_foreach(struct option_dialog *pdialog,
473 void (*option_action)
474 (struct option *))
476 fc_assert_ret(NULL != pdialog);
478 options_iterate(pdialog->poptset, poption) {
479 option_action(poption);
480 } options_iterate_end;
483 /****************************************************************************
484 Add an option to the option dialog.
485 ****************************************************************************/
486 static void option_dialog_option_add(struct option_dialog *pdialog,
487 struct option *poption,
488 bool reorder_notebook)
490 const int category = option_category(poption);
491 GtkWidget *main_hbox, *label, *ebox, *w = NULL;
493 fc_assert(NULL == option_get_gui_data(poption));
495 /* Add category if needed. */
496 if (NULL == pdialog->vboxes[category]) {
497 GtkWidget *sw;
499 sw = gtk_scrolled_window_new(NULL, NULL);
500 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
501 GTK_POLICY_NEVER,
502 GTK_POLICY_AUTOMATIC);
503 g_object_set_data(G_OBJECT(sw), "category", GINT_TO_POINTER(category));
504 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), sw,
505 gtk_label_new_with_mnemonic
506 (option_category_name(poption)));
508 if (reorder_notebook) {
509 option_dialog_reorder_notebook(pdialog);
512 pdialog->vboxes[category] = gtk_grid_new();
513 gtk_orientable_set_orientation(GTK_ORIENTABLE(pdialog->vboxes[category]),
514 GTK_ORIENTATION_VERTICAL);
515 g_object_set(pdialog->vboxes[category], "margin", 8, NULL);
516 gtk_widget_set_hexpand(pdialog->vboxes[category], TRUE);
517 gtk_container_add(GTK_CONTAINER(sw), pdialog->vboxes[category]);
519 gtk_widget_show_all(sw);
521 pdialog->box_children[category]++;
523 ebox = gtk_event_box_new();
524 gtk_widget_set_tooltip_text(ebox, option_help_text(poption));
525 gtk_container_add(GTK_CONTAINER(pdialog->vboxes[category]), ebox);
526 g_signal_connect(ebox, "button_press_event",
527 G_CALLBACK(option_button_press_callback), poption);
529 main_hbox = gtk_grid_new();
530 label = gtk_label_new(option_description(poption));
531 g_object_set(label, "margin", 2, NULL);
532 gtk_container_add(GTK_CONTAINER(main_hbox), label);
533 gtk_container_add(GTK_CONTAINER(ebox), main_hbox);
535 switch (option_type(poption)) {
536 case OT_BOOLEAN:
537 w = gtk_check_button_new();
538 break;
540 case OT_INTEGER:
542 int min = option_int_min(poption), max = option_int_max(poption);
544 w = gtk_spin_button_new_with_range(min, max, MAX((max - min) / 50, 1));
546 break;
548 case OT_STRING:
550 const struct strvec *values = option_str_values(poption);
552 if (NULL != values) {
553 w = gtk_combo_box_text_new_with_entry();
554 strvec_iterate(values, value) {
555 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(w), value);
556 } strvec_iterate_end;
557 } else {
558 w = gtk_entry_new();
561 break;
563 case OT_ENUM:
565 int i;
566 const char *str;
567 GtkListStore *model;
568 GtkCellRenderer *renderer;
569 GtkTreeIter iter;
571 /* 0: enum index, 1: translated enum name. */
572 model = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
573 w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
574 g_object_unref(model);
576 renderer = gtk_cell_renderer_text_new();
577 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), renderer, FALSE);
578 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), renderer,
579 "text", 1, NULL);
580 for (i = 0; (str = option_enum_int_to_str(poption, i)); i++) {
581 gtk_list_store_append(model, &iter);
582 gtk_list_store_set(model, &iter, 0, i, 1, _(str), -1);
585 break;
587 case OT_BITWISE:
589 GList *list = NULL;
590 GtkWidget *grid, *check;
591 const struct strvec *values = option_bitwise_values(poption);
592 int i;
594 w = gtk_frame_new(NULL);
595 grid = gtk_grid_new();
596 gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
597 gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
598 gtk_container_add(GTK_CONTAINER(w), grid);
599 for (i = 0; i < strvec_size(values); i++) {
600 check = gtk_check_button_new();
601 gtk_grid_attach(GTK_GRID(grid), check, 0, i, 1, 1);
602 label = gtk_label_new(_(strvec_get(values, i)));
603 gtk_grid_attach(GTK_GRID(grid), label, 1, i, 1, 1);
604 list = g_list_append(list, check);
606 g_object_set_data_full(G_OBJECT(w), "check_buttons", list,
607 (GDestroyNotify) g_list_free);
609 break;
611 case OT_FONT:
612 w = gtk_font_button_new();
613 g_object_set(G_OBJECT(w), "use-font", TRUE, NULL);
614 break;
616 case OT_COLOR:
618 GtkWidget *button;
620 w = gtk_grid_new();
621 gtk_grid_set_column_spacing(GTK_GRID(w), 4);
622 gtk_grid_set_row_homogeneous(GTK_GRID(w), TRUE);
624 /* Foreground color selector button. */
625 button = gtk_button_new();
626 gtk_container_add(GTK_CONTAINER(w), button);
627 gtk_widget_set_tooltip_text(GTK_WIDGET(button),
628 _("Select the text color"));
629 g_object_set_data(G_OBJECT(w), "fg_button", button);
630 g_signal_connect(button, "clicked",
631 G_CALLBACK(option_color_select_callback), NULL);
633 /* Background color selector button. */
634 button = gtk_button_new();
635 gtk_container_add(GTK_CONTAINER(w), button);
636 gtk_widget_set_tooltip_text(GTK_WIDGET(button),
637 _("Select the background color"));
638 g_object_set_data(G_OBJECT(w), "bg_button", button);
639 g_signal_connect(button, "clicked",
640 G_CALLBACK(option_color_select_callback), NULL);
642 break;
644 case OT_VIDEO_MODE:
645 log_error("Option type %s (%d) not supported yet.",
646 option_type_name(option_type(poption)),
647 option_type(poption));
648 break;
651 option_set_gui_data(poption, w);
652 if (NULL == w) {
653 log_error("Failed to create a widget for option %d \"%s\".",
654 option_number(poption), option_name(poption));
655 } else {
656 g_object_set_data(G_OBJECT(w), "main_widget", ebox);
657 gtk_widget_set_hexpand(w, TRUE);
658 gtk_widget_set_halign(w, GTK_ALIGN_END);
659 gtk_container_add(GTK_CONTAINER(main_hbox), w);
662 gtk_widget_show_all(ebox);
664 /* Set as current value. */
665 option_dialog_option_refresh(poption);
668 /****************************************************************************
669 Remove an option from the option dialog.
670 ****************************************************************************/
671 static void option_dialog_option_remove(struct option_dialog *pdialog,
672 struct option *poption)
674 GObject *object = G_OBJECT(option_get_gui_data(poption));
676 if (NULL != object) {
677 const int category = option_category(poption);
679 option_set_gui_data(poption, NULL);
680 gtk_widget_destroy(GTK_WIDGET(g_object_get_data(object, "main_widget")));
682 /* Remove category if needed. */
683 if (0 == --pdialog->box_children[category]) {
684 gtk_notebook_remove_page(GTK_NOTEBOOK(pdialog->notebook), category);
685 pdialog->vboxes[category] = NULL;
690 /****************************************************************************
691 Set the boolean value of the option.
692 ****************************************************************************/
693 static inline void option_dialog_option_bool_set(struct option *poption,
694 bool value)
696 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
697 (option_get_gui_data(poption)),
698 value);
701 /****************************************************************************
702 Set the integer value of the option.
703 ****************************************************************************/
704 static inline void option_dialog_option_int_set(struct option *poption,
705 int value)
707 gtk_spin_button_set_value(GTK_SPIN_BUTTON(option_get_gui_data(poption)),
708 value);
711 /****************************************************************************
712 Set the string value of the option.
713 ****************************************************************************/
714 static inline void option_dialog_option_str_set(struct option *poption,
715 const char *string)
717 if (NULL != option_str_values(poption)) {
718 gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN
719 (option_get_gui_data(poption)))), string);
720 } else {
721 gtk_entry_set_text(GTK_ENTRY(option_get_gui_data(poption)), string);
725 /****************************************************************************
726 Set the enum value of the option.
727 ****************************************************************************/
728 static inline void option_dialog_option_enum_set(struct option *poption,
729 int value)
731 GtkComboBox *combo = GTK_COMBO_BOX(option_get_gui_data(poption));
732 GtkTreeModel *model = gtk_combo_box_get_model(combo);
733 GtkTreeIter iter;
734 int i;
736 if (gtk_tree_model_get_iter_first(model, &iter)) {
737 do {
738 gtk_tree_model_get(model, &iter, 0, &i, -1);
739 if (i == value) {
740 gtk_combo_box_set_active_iter(combo, &iter);
741 return;
743 } while (gtk_tree_model_iter_next(model, &iter));
746 log_error("Didn't find the value %d for option \"%s\" (nb %d).",
747 value, option_name(poption), option_number(poption));
750 /****************************************************************************
751 Set the enum value of the option.
752 ****************************************************************************/
753 static inline void option_dialog_option_bitwise_set(struct option *poption,
754 unsigned value)
756 GObject *data = option_get_gui_data(poption);
757 GList *iter = g_object_get_data(data, "check_buttons");
758 int bit;
760 for (bit = 0; NULL != iter; iter = g_list_next(iter), bit++) {
761 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(iter->data),
762 value & (1 << bit));
766 /****************************************************************************
767 Set the font value of the option.
768 ****************************************************************************/
769 static inline void option_dialog_option_font_set(struct option *poption,
770 const char *font)
772 gtk_font_button_set_font_name(GTK_FONT_BUTTON
773 (option_get_gui_data(poption)), font);
776 /****************************************************************************
777 Set the font value of the option.
778 ****************************************************************************/
779 static inline void option_dialog_option_color_set(struct option *poption,
780 struct ft_color color)
782 GtkWidget *w = option_get_gui_data(poption);
783 GdkRGBA gdk_color;
785 /* Update the foreground button. */
786 if (NULL != color.foreground
787 && '\0' != color.foreground[0]
788 && gdk_rgba_parse(&gdk_color, color.foreground)) {
789 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
790 "fg_button"),
791 &gdk_color);
792 } else {
793 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
794 "fg_button"), NULL);
797 /* Update the background button. */
798 if (NULL != color.background
799 && '\0' != color.background[0]
800 && gdk_rgba_parse(&gdk_color, color.background)) {
801 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
802 "bg_button"),
803 &gdk_color);
804 } else {
805 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
806 "bg_button"), NULL);
810 /****************************************************************************
811 Update an option in the option dialog.
812 ****************************************************************************/
813 static void option_dialog_option_refresh(struct option *poption)
815 switch (option_type(poption)) {
816 case OT_BOOLEAN:
817 option_dialog_option_bool_set(poption, option_bool_get(poption));
818 break;
819 case OT_INTEGER:
820 option_dialog_option_int_set(poption, option_int_get(poption));
821 break;
822 case OT_STRING:
823 option_dialog_option_str_set(poption, option_str_get(poption));
824 break;
825 case OT_ENUM:
826 option_dialog_option_enum_set(poption, option_enum_get_int(poption));
827 break;
828 case OT_BITWISE:
829 option_dialog_option_bitwise_set(poption, option_bitwise_get(poption));
830 break;
831 case OT_FONT:
832 option_dialog_option_font_set(poption, option_font_get(poption));
833 break;
834 case OT_COLOR:
835 option_dialog_option_color_set(poption, option_color_get(poption));
836 break;
837 case OT_VIDEO_MODE:
838 log_error("Option type %s (%d) not supported yet.",
839 option_type_name(option_type(poption)),
840 option_type(poption));
841 break;
844 gtk_widget_set_sensitive(option_get_gui_data(poption),
845 option_is_changeable(poption));
848 /****************************************************************************
849 Reset the option.
850 ****************************************************************************/
851 static void option_dialog_option_reset(struct option *poption)
853 switch (option_type(poption)) {
854 case OT_BOOLEAN:
855 option_dialog_option_bool_set(poption, option_bool_def(poption));
856 break;
857 case OT_INTEGER:
858 option_dialog_option_int_set(poption, option_int_def(poption));
859 break;
860 case OT_STRING:
861 option_dialog_option_str_set(poption, option_str_def(poption));
862 break;
863 case OT_ENUM:
864 option_dialog_option_enum_set(poption, option_enum_def_int(poption));
865 break;
866 case OT_BITWISE:
867 option_dialog_option_bitwise_set(poption, option_bitwise_def(poption));
868 break;
869 case OT_FONT:
870 option_dialog_option_font_set(poption, option_font_def(poption));
871 break;
872 case OT_COLOR:
873 option_dialog_option_color_set(poption, option_color_def(poption));
874 break;
875 case OT_VIDEO_MODE:
876 log_error("Option type %s (%d) not supported yet.",
877 option_type_name(option_type(poption)),
878 option_type(poption));
879 break;
883 /****************************************************************************
884 Apply the option change.
885 ****************************************************************************/
886 static void option_dialog_option_apply(struct option *poption)
888 GtkWidget *w = GTK_WIDGET(option_get_gui_data(poption));
890 switch (option_type(poption)) {
891 case OT_BOOLEAN:
892 (void) option_bool_set(poption, gtk_toggle_button_get_active
893 (GTK_TOGGLE_BUTTON(w)));
894 break;
896 case OT_INTEGER:
897 (void) option_int_set(poption, gtk_spin_button_get_value_as_int
898 (GTK_SPIN_BUTTON(w)));
899 break;
901 case OT_STRING:
902 if (NULL != option_str_values(poption)) {
903 (void) option_str_set(poption, gtk_entry_get_text
904 (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(w)))));
905 } else {
906 (void) option_str_set(poption, gtk_entry_get_text(GTK_ENTRY(w)));
908 break;
910 case OT_ENUM:
912 GtkTreeIter iter;
913 int value;
915 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w), &iter)) {
916 break;
919 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(w)),
920 &iter, 0, &value, -1);
921 (void) option_enum_set_int(poption, value);
923 break;
925 case OT_BITWISE:
927 GList *iter = g_object_get_data(G_OBJECT(w), "check_buttons");
928 unsigned value = 0;
929 int bit;
931 for (bit = 0; NULL != iter; iter = g_list_next(iter), bit++) {
932 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(iter->data))) {
933 value |= 1 << bit;
936 (void) option_bitwise_set(poption, value);
938 break;
940 case OT_FONT:
941 (void) option_font_set(poption, gtk_font_button_get_font_name
942 (GTK_FONT_BUTTON(w)));
943 break;
945 case OT_COLOR:
947 gchar *fg_color_text = NULL, *bg_color_text = NULL;
948 GObject *button;
949 GdkRGBA *color;
951 /* Get foreground color. */
952 button = g_object_get_data(G_OBJECT(w), "fg_button");
953 color = g_object_get_data(button, "color");
954 if (color) fg_color_text = gdk_rgba_to_string(color);
956 /* Get background color. */
957 button = g_object_get_data(G_OBJECT(w), "bg_button");
958 color = g_object_get_data(button, "color");
959 if (color) bg_color_text = gdk_rgba_to_string(color);
961 (void) option_color_set(poption,
962 ft_color_construct(fg_color_text, bg_color_text));
963 g_free(fg_color_text);
964 g_free(bg_color_text);
966 break;
968 case OT_VIDEO_MODE:
969 log_error("Option type %s (%d) not supported yet.",
970 option_type_name(option_type(poption)),
971 option_type(poption));
972 break;
976 /****************************************************************************
977 Popup the option dialog for the option set.
978 ****************************************************************************/
979 void option_dialog_popup(const char *name, const struct option_set *poptset)
981 struct option_dialog *pdialog = option_dialog_get(poptset);
983 if (NULL != pdialog) {
984 option_dialog_foreach(pdialog, option_dialog_option_refresh);
985 } else {
986 (void) option_dialog_new(name, poptset);
990 /****************************************************************************
991 Popdown the option dialog for the option set.
992 ****************************************************************************/
993 void option_dialog_popdown(const struct option_set *poptset)
995 struct option_dialog *pdialog = option_dialog_get(poptset);
997 if (NULL != pdialog) {
998 option_dialog_destroy(pdialog);
1002 /****************************************************************************
1003 Pass on updated option values to controls outside the main option
1004 dialogs.
1005 ****************************************************************************/
1006 static void option_gui_update_extra(struct option *poption)
1008 if (option_optset(poption) == server_optset) {
1009 if (strcmp(option_name(poption), "aifill") == 0) {
1010 ai_fill_changed_by_server(option_int_get(poption));
1011 } else if (strcmp(option_name(poption), "nationset") == 0) {
1012 nationset_sync_to_server(option_str_get(poption));
1017 /****************************************************************************
1018 Update the GUI for the option.
1019 ****************************************************************************/
1020 void option_gui_update(struct option *poption)
1022 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1024 if (NULL != pdialog) {
1025 option_dialog_option_refresh(poption);
1028 option_gui_update_extra(poption);
1031 /****************************************************************************
1032 Add the GUI for the option.
1033 ****************************************************************************/
1034 void option_gui_add(struct option *poption)
1036 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1038 if (NULL != pdialog) {
1039 option_dialog_option_add(pdialog, poption, TRUE);
1042 option_gui_update_extra(poption);
1045 /****************************************************************************
1046 Remove the GUI for the option.
1047 ****************************************************************************/
1048 void option_gui_remove(struct option *poption)
1050 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1052 if (NULL != pdialog) {
1053 option_dialog_option_remove(pdialog, poption);