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)
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 ***********************************************************************/
15 #include <fc_config.h>
25 #include "string_vector.h"
30 /* client/gui-gtk-3.0 */
34 #include "gui_stuff.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
50 #define SPECLIST_TAG option_dialog
51 #define SPECLIST_TYPE struct option_dialog
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
;
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
,
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
));
107 option_dialog_foreach(pdialog
, option_dialog_option_apply
);
108 gtk_widget_destroy(GTK_WIDGET(dialog
));
111 option_dialog_foreach(pdialog
, option_dialog_option_apply
);
114 option_dialog_foreach(pdialog
, option_dialog_option_reset
);
116 case RESPONSE_REFRESH
:
117 option_dialog_foreach(pdialog
, option_dialog_option_refresh
);
120 desired_settable_options_update();
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
,
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! */
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);
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
) {
235 } option_dialogs_iterate_end
;
240 /****************************************************************************
241 GDestroyNotify callback.
242 ****************************************************************************/
243 static void option_color_destroy_notify(gpointer data
)
245 GdkRGBA
*color
= (GdkRGBA
*) data
;
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");
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
);
271 /* Apply the new color. */
272 if (NULL
!= current_color
) {
273 /* We already have a GdkRGBA pointer. */
274 *current_color
= *new_color
;
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
);
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"));
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
,
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
,
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
);
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
);
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
;
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
);
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
);
456 GtkWidget
*pages
[pages_num
];
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
)
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
]) {
499 sw
= gtk_scrolled_window_new(NULL
, NULL
);
500 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw
),
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
)) {
537 w
= gtk_check_button_new();
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));
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
;
568 GtkCellRenderer
*renderer
;
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
,
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);
590 GtkWidget
*grid
, *check
;
591 const struct strvec
*values
= option_bitwise_values(poption
);
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
);
612 w
= gtk_font_button_new();
613 g_object_set(G_OBJECT(w
), "use-font", TRUE
, NULL
);
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
);
645 log_error("Option type %s (%d) not supported yet.",
646 option_type_name(option_type(poption
)),
647 option_type(poption
));
651 option_set_gui_data(poption
, w
);
653 log_error("Failed to create a widget for option %d \"%s\".",
654 option_number(poption
), option_name(poption
));
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
,
696 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
697 (option_get_gui_data(poption
)),
701 /****************************************************************************
702 Set the integer value of the option.
703 ****************************************************************************/
704 static inline void option_dialog_option_int_set(struct option
*poption
,
707 gtk_spin_button_set_value(GTK_SPIN_BUTTON(option_get_gui_data(poption
)),
711 /****************************************************************************
712 Set the string value of the option.
713 ****************************************************************************/
714 static inline void option_dialog_option_str_set(struct option
*poption
,
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
);
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
,
731 GtkComboBox
*combo
= GTK_COMBO_BOX(option_get_gui_data(poption
));
732 GtkTreeModel
*model
= gtk_combo_box_get_model(combo
);
736 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
738 gtk_tree_model_get(model
, &iter
, 0, &i
, -1);
740 gtk_combo_box_set_active_iter(combo
, &iter
);
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
,
756 GObject
*data
= option_get_gui_data(poption
);
757 GList
*iter
= g_object_get_data(data
, "check_buttons");
760 for (bit
= 0; NULL
!= iter
; iter
= g_list_next(iter
), bit
++) {
761 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(iter
->data
),
766 /****************************************************************************
767 Set the font value of the option.
768 ****************************************************************************/
769 static inline void option_dialog_option_font_set(struct option
*poption
,
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
);
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
),
793 option_color_set_button_color(g_object_get_data(G_OBJECT(w
),
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
),
805 option_color_set_button_color(g_object_get_data(G_OBJECT(w
),
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
)) {
817 option_dialog_option_bool_set(poption
, option_bool_get(poption
));
820 option_dialog_option_int_set(poption
, option_int_get(poption
));
823 option_dialog_option_str_set(poption
, option_str_get(poption
));
826 option_dialog_option_enum_set(poption
, option_enum_get_int(poption
));
829 option_dialog_option_bitwise_set(poption
, option_bitwise_get(poption
));
832 option_dialog_option_font_set(poption
, option_font_get(poption
));
835 option_dialog_option_color_set(poption
, option_color_get(poption
));
838 log_error("Option type %s (%d) not supported yet.",
839 option_type_name(option_type(poption
)),
840 option_type(poption
));
844 gtk_widget_set_sensitive(option_get_gui_data(poption
),
845 option_is_changeable(poption
));
848 /****************************************************************************
850 ****************************************************************************/
851 static void option_dialog_option_reset(struct option
*poption
)
853 switch (option_type(poption
)) {
855 option_dialog_option_bool_set(poption
, option_bool_def(poption
));
858 option_dialog_option_int_set(poption
, option_int_def(poption
));
861 option_dialog_option_str_set(poption
, option_str_def(poption
));
864 option_dialog_option_enum_set(poption
, option_enum_def_int(poption
));
867 option_dialog_option_bitwise_set(poption
, option_bitwise_def(poption
));
870 option_dialog_option_font_set(poption
, option_font_def(poption
));
873 option_dialog_option_color_set(poption
, option_color_def(poption
));
876 log_error("Option type %s (%d) not supported yet.",
877 option_type_name(option_type(poption
)),
878 option_type(poption
));
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
)) {
892 (void) option_bool_set(poption
, gtk_toggle_button_get_active
893 (GTK_TOGGLE_BUTTON(w
)));
897 (void) option_int_set(poption
, gtk_spin_button_get_value_as_int
898 (GTK_SPIN_BUTTON(w
)));
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
)))));
906 (void) option_str_set(poption
, gtk_entry_get_text(GTK_ENTRY(w
)));
915 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w
), &iter
)) {
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
);
927 GList
*iter
= g_object_get_data(G_OBJECT(w
), "check_buttons");
931 for (bit
= 0; NULL
!= iter
; iter
= g_list_next(iter
), bit
++) {
932 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(iter
->data
))) {
936 (void) option_bitwise_set(poption
, value
);
941 (void) option_font_set(poption
, gtk_font_button_get_font_name
942 (GTK_FONT_BUTTON(w
)));
947 gchar
*fg_color_text
= NULL
, *bg_color_text
= NULL
;
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
);
969 log_error("Option type %s (%d) not supported yet.",
970 option_type_name(option_type(poption
)),
971 option_type(poption
));
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
);
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
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
);