Freeciv-3.1
Loading...
Searching...
No Matches
optiondlg.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 <stdlib.h>
19
20#include <gtk/gtk.h>
21
22/* utility */
23#include "log.h"
24#include "mem.h"
25#include "string_vector.h"
26
27/* client */
28#include "options.h"
29
30/* client/gui-gtk-3.22 */
31#include "colors.h"
32#include "dialogs.h"
33#include "gui_main.h"
34#include "gui_stuff.h"
35#include "pages.h"
36
37#include "optiondlg.h"
38
39static int opt_dlog_width = -1, opt_dlog_height = 480;
40
41/* The option dialog data. */
42struct option_dialog {
43 const struct option_set *poptset; /* The option set. */
44 GtkWidget *shell; /* The main widget. */
45 GtkWidget *notebook; /* The notebook. */
46 GtkWidget **vboxes; /* Category boxes. */
47 int *box_children; /* The number of children for
48 * each category. */
49};
50
51#define SPECLIST_TAG option_dialog
52#define SPECLIST_TYPE struct option_dialog
53#include "speclist.h"
54#define option_dialogs_iterate(pdialog) \
55 TYPED_LIST_ITERATE(struct option_dialog, option_dialogs, pdialog)
56#define option_dialogs_iterate_end LIST_ITERATE_END
57
58/* All option dialog are set on this list. */
59static struct option_dialog_list *option_dialogs = NULL;
60
61enum {
68};
69
70
71/* Option dialog main functions. */
72static struct option_dialog *
74static struct option_dialog *
75option_dialog_new(const char *name, const struct option_set *poptset);
76static void option_dialog_destroy(struct option_dialog *pdialog);
77
78static void option_dialog_reorder_notebook(struct option_dialog *pdialog);
79static inline void option_dialog_foreach(struct option_dialog *pdialog,
80 void (*option_action)
81 (struct option *));
82
83/* Option dialog option-specific functions. */
84static void option_dialog_option_add(struct option_dialog *pdialog,
85 struct option *poption,
86 bool reorder_notebook);
87static void option_dialog_option_remove(struct option_dialog *pdialog,
88 struct option *poption);
89
90static void option_dialog_option_refresh(struct option *poption);
91static void option_dialog_option_reset(struct option *poption);
92static void option_dialog_option_apply(struct option *poption);
93
94
95/************************************************************************/
98static void option_dialog_reponse_callback(GtkDialog *dialog,
99 gint response_id, gpointer data)
100{
101 struct option_dialog *pdialog = (struct option_dialog *) data;
102
103 switch (response_id) {
104 case RESPONSE_CANCEL:
105 gtk_widget_destroy(GTK_WIDGET(dialog));
106 break;
107 case RESPONSE_OK:
109 gtk_widget_destroy(GTK_WIDGET(dialog));
110 break;
111 case RESPONSE_APPLY:
113 break;
114 case RESPONSE_RESET:
116 break;
117 case RESPONSE_REFRESH:
119 break;
120 case RESPONSE_SAVE:
122 options_save(NULL);
123 break;
124 }
125}
126
127/************************************************************************/
130static void option_dialog_destroy_callback(GtkWidget *object, gpointer data)
131{
132 struct option_dialog *pdialog = (struct option_dialog *) data;
133 GtkWidget* cont_area;
134 GtkAllocation allocation;
135 int baseline;
136
137 /* Save size of the dialog. */
138 cont_area = gtk_dialog_get_content_area (GTK_DIALOG(pdialog->shell));
139 gtk_widget_get_allocated_size(GTK_WIDGET(cont_area),
140 &allocation, &baseline);
141 opt_dlog_width = allocation.width;
142 opt_dlog_height = allocation.height;
143
144 if (NULL != pdialog->shell) {
145 /* Mark as destroyed, see also option_dialog_destroy(). */
146 pdialog->shell = NULL;
147 option_dialog_destroy(pdialog);
148 }
149}
150
151/************************************************************************/
154static void option_refresh_callback(GtkMenuItem *menuitem, gpointer data)
155{
156 struct option *poption = (struct option *) data;
157 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
158
159 if (NULL != pdialog) {
161 }
162}
163
164/************************************************************************/
167static void option_reset_callback(GtkMenuItem *menuitem, gpointer data)
168{
169 struct option *poption = (struct option *) data;
170 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
171
172 if (NULL != pdialog) {
174 }
175}
176
177/************************************************************************/
180static void option_apply_callback(GtkMenuItem *menuitem, gpointer data)
181{
182 struct option *poption = (struct option *) data;
183 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
184
185 if (NULL != pdialog) {
187 }
188}
189
190/************************************************************************/
193static gboolean option_button_press_callback(GtkWidget *widget,
194 GdkEventButton *event,
195 gpointer data)
196{
197 struct option *poption = (struct option *) data;
198 GtkWidget *menu, *item;
199
200 if (3 != event->button || !option_is_changeable(poption)) {
201 /* Only right button please! */
202 return FALSE;
203 }
204
205 menu = gtk_menu_new();
206
207 item = gtk_menu_item_new_with_label(_("Refresh this option"));
208 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
209 g_signal_connect(item, "activate",
210 G_CALLBACK(option_refresh_callback), poption);
211
212 item = gtk_menu_item_new_with_label(_("Reset this option"));
213 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
214 g_signal_connect(item, "activate",
215 G_CALLBACK(option_reset_callback), poption);
216
217 item = gtk_menu_item_new_with_label(_("Apply the changes for this option"));
218 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
219 g_signal_connect(item, "activate",
220 G_CALLBACK(option_apply_callback), poption);
221
222 gtk_widget_show_all(menu);
223 gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
224
225 return TRUE;
226}
227
228/************************************************************************/
231static struct option_dialog *
233{
234 if (NULL != option_dialogs) {
235 option_dialogs_iterate(pdialog) {
236 if (pdialog->poptset == poptset) {
237 return pdialog;
238 }
240 }
241 return NULL;
242}
243
244/************************************************************************/
247static void option_color_destroy_notify(gpointer data)
248{
249 GdkRGBA *color = (GdkRGBA *) data;
250
251 if (NULL != color) {
252 gdk_rgba_free(color);
253 }
254}
255
256/************************************************************************/
259static void option_color_set_button_color(GtkButton *button,
260 const GdkRGBA *new_color)
261{
262 GdkRGBA *current_color = g_object_get_data(G_OBJECT(button), "color");
263 GtkWidget *child;
264
265 if (NULL == new_color) {
266 if (NULL != current_color) {
267 g_object_set_data(G_OBJECT(button), "color", NULL);
268 if ((child = gtk_bin_get_child(GTK_BIN(button)))) {
269 gtk_widget_destroy(child);
270 }
271 }
272 } else {
273 GdkPixbuf *pixbuf;
274
275 /* Apply the new color. */
276 if (NULL != current_color) {
277 /* We already have a GdkRGBA pointer. */
278 *current_color = *new_color;
279 } else {
280 /* We need to make a GdkRGBA pointer. */
281 current_color = gdk_rgba_copy(new_color);
282 g_object_set_data_full(G_OBJECT(button), "color", current_color,
284 }
285 if ((child = gtk_bin_get_child(GTK_BIN(button)))) {
286 gtk_widget_destroy(child);
287 }
288
289 /* Update the button. */
290 {
291 cairo_surface_t *surface = cairo_image_surface_create(
292 CAIRO_FORMAT_RGB24, 16, 16);
293 cairo_t *cr = cairo_create(surface);
294 gdk_cairo_set_source_rgba(cr, current_color);
295 cairo_paint(cr);
296 cairo_destroy(cr);
297 pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, 16, 16);
298 cairo_surface_destroy(surface);
299 }
300 child = gtk_image_new_from_pixbuf(pixbuf);
301 gtk_container_add(GTK_CONTAINER(button), child);
302 gtk_widget_show(child);
303 g_object_unref(G_OBJECT(pixbuf));
304 }
305}
306
307/************************************************************************/
310static void color_selector_response_callback(GtkDialog *dialog,
311 gint res, gpointer data)
312{
313 if (res == GTK_RESPONSE_REJECT) {
314 /* Clears the current color. */
315 option_color_set_button_color(GTK_BUTTON(data), NULL);
316 } else if (res == GTK_RESPONSE_OK) {
317 /* Apply the new color. */
318 GtkColorChooser *chooser =
319 GTK_COLOR_CHOOSER(g_object_get_data(G_OBJECT(dialog), "chooser"));
320 GdkRGBA new_color;
321
322 gtk_color_chooser_get_rgba(chooser, &new_color);
323 option_color_set_button_color(GTK_BUTTON(data), &new_color);
324 }
325
326 gtk_widget_destroy(GTK_WIDGET(dialog));
327}
328
329/************************************************************************/
332static void option_color_select_callback(GtkButton *button, gpointer data)
333{
334 GtkWidget *dialog, *chooser;
335 GdkRGBA *current_color = g_object_get_data(G_OBJECT(button), "color");
336
337 dialog = gtk_dialog_new_with_buttons(_("Select a color"), NULL,
338 GTK_DIALOG_MODAL,
339 _("_Cancel"), GTK_RESPONSE_CANCEL,
340 _("C_lear"), GTK_RESPONSE_REJECT,
341 _("_OK"), GTK_RESPONSE_OK, NULL);
342 setup_dialog(dialog, toplevel);
343 g_signal_connect(dialog, "response",
344 G_CALLBACK(color_selector_response_callback), button);
345
346 chooser = gtk_color_chooser_widget_new();
347 g_object_set_data(G_OBJECT(dialog), "chooser", chooser);
348 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), chooser,
349 FALSE, FALSE, 0);
350 if (current_color) {
351 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(chooser), current_color);
352 }
353
354 gtk_widget_show_all(dialog);
355}
356
357
358/************************************************************************/
361static struct option_dialog *
362option_dialog_new(const char *name, const struct option_set *poptset)
363{
364 struct option_dialog *pdialog;
365 const int CATEGORY_NUM = optset_category_number(poptset);
366
367 /* Create the dialog structure. */
368 pdialog = fc_malloc(sizeof(*pdialog));
369 pdialog->poptset = poptset;
370 pdialog->shell = gtk_dialog_new_with_buttons(name, NULL, 0,
371 _("_Cancel"), RESPONSE_CANCEL,
372 _("_Save"), RESPONSE_SAVE,
373 _("_Refresh"), RESPONSE_REFRESH,
374 _("Reset"), RESPONSE_RESET,
375 _("_Apply"), RESPONSE_APPLY,
376 _("_OK"), RESPONSE_OK, NULL);
377 pdialog->notebook = gtk_notebook_new();
378 pdialog->vboxes = fc_calloc(CATEGORY_NUM, sizeof(*pdialog->vboxes));
379 pdialog->box_children = fc_calloc(CATEGORY_NUM,
380 sizeof(*pdialog->box_children));
381
382 /* Append to the option dialog list. */
383 if (NULL == option_dialogs) {
384 option_dialogs = option_dialog_list_new();
385 }
386 option_dialog_list_append(option_dialogs, pdialog);
387
388 /* Shell */
389 setup_dialog(pdialog->shell, toplevel);
390 gtk_window_set_position(GTK_WINDOW(pdialog->shell), GTK_WIN_POS_MOUSE);
391 gtk_window_set_default_size(GTK_WINDOW(pdialog->shell),
394 g_signal_connect(pdialog->shell, "response",
395 G_CALLBACK(option_dialog_reponse_callback), pdialog);
396 g_signal_connect(pdialog->shell, "destroy",
397 G_CALLBACK(option_dialog_destroy_callback), pdialog);
398
399 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(pdialog->shell))),
400 pdialog->notebook, TRUE, TRUE, 0);
401
402 /* Add the options. */
403 options_iterate(poptset, poption) {
404 option_dialog_option_add(pdialog, poption, FALSE);
406
408
409 /* Show the widgets. */
410 gtk_widget_show_all(pdialog->shell);
411
412 return pdialog;
413}
414
415/************************************************************************/
418static void option_dialog_destroy(struct option_dialog *pdialog)
419{
420 GtkWidget *shell = pdialog->shell;
421
422 if (NULL != option_dialogs) {
423 option_dialog_list_remove(option_dialogs, pdialog);
424 }
425
426 options_iterate(pdialog->poptset, poption) {
427 option_set_gui_data(poption, NULL);
429
430 if (NULL != shell) {
431 /* Maybe already destroyed, see also option_dialog_destroy_callback(). */
432 pdialog->shell = NULL;
433 gtk_widget_destroy(shell);
434 }
435
436 free(pdialog->vboxes);
437 free(pdialog->box_children);
438 free(pdialog);
439}
440
441/************************************************************************/
444static int option_dialog_pages_sort_func(const void *w1, const void *w2)
445{
446 GObject *obj1 = G_OBJECT(*(GtkWidget **) w1);
447 GObject *obj2 = G_OBJECT(*(GtkWidget **) w2);
448
449 return (GPOINTER_TO_INT(g_object_get_data(obj1, "category"))
450 - GPOINTER_TO_INT(g_object_get_data(obj2, "category")));
451}
452
453/************************************************************************/
457{
458 GtkNotebook *notebook = GTK_NOTEBOOK(pdialog->notebook);
459 const int pages_num = gtk_notebook_get_n_pages(notebook);
460
461 if (0 < pages_num) {
462 GtkWidget *pages[pages_num];
463 int i;
464
465 for (i = 0; i < pages_num; i++) {
466 pages[i] = gtk_notebook_get_nth_page(notebook, i);
467 }
468 qsort(pages, pages_num, sizeof(*pages), option_dialog_pages_sort_func);
469 for (i = 0; i < pages_num; i++) {
470 gtk_notebook_reorder_child(notebook, pages[i], i);
471 }
472 }
473}
474
475/************************************************************************/
478static inline void option_dialog_foreach(struct option_dialog *pdialog,
479 void (*option_action)
480 (struct option *))
481{
482 fc_assert_ret(NULL != pdialog);
483
484 options_iterate(pdialog->poptset, poption) {
485 option_action(poption);
487}
488
489/************************************************************************/
492static void option_dialog_option_add(struct option_dialog *pdialog,
493 struct option *poption,
494 bool reorder_notebook)
495{
496 const int category = option_category(poption);
497 GtkWidget *main_hbox, *label, *ebox, *w = NULL;
498
499 fc_assert(NULL == option_get_gui_data(poption));
500
501 /* Add category if needed. */
502 if (NULL == pdialog->vboxes[category]) {
503 GtkWidget *sw;
504
505 sw = gtk_scrolled_window_new(NULL, NULL);
506 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
507 GTK_POLICY_NEVER,
508 GTK_POLICY_AUTOMATIC);
509 g_object_set_data(G_OBJECT(sw), "category", GINT_TO_POINTER(category));
510 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), sw,
511 gtk_label_new_with_mnemonic
512 (option_category_name(poption)));
513
514 if (reorder_notebook) {
516 }
517
518 pdialog->vboxes[category] = gtk_grid_new();
519 gtk_orientable_set_orientation(GTK_ORIENTABLE(pdialog->vboxes[category]),
520 GTK_ORIENTATION_VERTICAL);
521 g_object_set(pdialog->vboxes[category], "margin", 8, NULL);
522 gtk_widget_set_hexpand(pdialog->vboxes[category], TRUE);
523 gtk_container_add(GTK_CONTAINER(sw), pdialog->vboxes[category]);
524
525 gtk_widget_show_all(sw);
526 }
527 pdialog->box_children[category]++;
528
529 ebox = gtk_event_box_new();
530 gtk_widget_set_tooltip_text(ebox, option_help_text(poption));
531 gtk_container_add(GTK_CONTAINER(pdialog->vboxes[category]), ebox);
532 g_signal_connect(ebox, "button_press_event",
533 G_CALLBACK(option_button_press_callback), poption);
534
535 main_hbox = gtk_grid_new();
536 label = gtk_label_new(option_description(poption));
537 g_object_set(label, "margin", 2, NULL);
538 gtk_container_add(GTK_CONTAINER(main_hbox), label);
539 gtk_container_add(GTK_CONTAINER(ebox), main_hbox);
540
541 switch (option_type(poption)) {
542 case OT_BOOLEAN:
543 w = gtk_check_button_new();
544 break;
545
546 case OT_INTEGER:
547 {
548 int min = option_int_min(poption), max = option_int_max(poption);
549
550 w = gtk_spin_button_new_with_range(min, max, MAX((max - min) / 50, 1));
551 }
552 break;
553
554 case OT_STRING:
555 {
556 const struct strvec *values = option_str_values(poption);
557
558 if (NULL != values) {
559 w = gtk_combo_box_text_new_with_entry();
560 strvec_iterate(values, value) {
561 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(w), value);
563 } else {
564 w = gtk_entry_new();
565 }
566 }
567 break;
568
569 case OT_ENUM:
570 {
571 int i;
572 const char *str;
573 GtkListStore *model;
574 GtkCellRenderer *renderer;
575 GtkTreeIter iter;
576
577 /* 0: enum index, 1: translated enum name. */
578 model = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
579 w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
580 g_object_unref(model);
581
582 renderer = gtk_cell_renderer_text_new();
583 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), renderer, FALSE);
584 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), renderer,
585 "text", 1, NULL);
586 for (i = 0; (str = option_enum_int_to_str(poption, i)); i++) {
587 gtk_list_store_append(model, &iter);
588 gtk_list_store_set(model, &iter, 0, i, 1, _(str), -1);
589 }
590 }
591 break;
592
593 case OT_BITWISE:
594 {
595 GList *list = NULL;
596 GtkWidget *grid, *check;
597 const struct strvec *values = option_bitwise_values(poption);
598 int i;
599
600 w = gtk_frame_new(NULL);
601 grid = gtk_grid_new();
602 gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
603 gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
604 gtk_container_add(GTK_CONTAINER(w), grid);
605 for (i = 0; i < strvec_size(values); i++) {
606 check = gtk_check_button_new();
607 gtk_grid_attach(GTK_GRID(grid), check, 0, i, 1, 1);
608 label = gtk_label_new(_(strvec_get(values, i)));
609 gtk_grid_attach(GTK_GRID(grid), label, 1, i, 1, 1);
610 list = g_list_append(list, check);
611 }
612 g_object_set_data_full(G_OBJECT(w), "check_buttons", list,
613 (GDestroyNotify) g_list_free);
614 }
615 break;
616
617 case OT_FONT:
618 w = gtk_font_button_new();
619 g_object_set(G_OBJECT(w), "use-font", TRUE, NULL);
620 break;
621
622 case OT_COLOR:
623 {
624 GtkWidget *button;
625
626 w = gtk_grid_new();
627 gtk_grid_set_column_spacing(GTK_GRID(w), 4);
628 gtk_grid_set_row_homogeneous(GTK_GRID(w), TRUE);
629
630 /* Foreground color selector button. */
631 button = gtk_button_new();
632 gtk_container_add(GTK_CONTAINER(w), button);
633 gtk_widget_set_tooltip_text(GTK_WIDGET(button),
634 _("Select the text color"));
635 g_object_set_data(G_OBJECT(w), "fg_button", button);
636 g_signal_connect(button, "clicked",
637 G_CALLBACK(option_color_select_callback), NULL);
638
639 /* Background color selector button. */
640 button = gtk_button_new();
641 gtk_container_add(GTK_CONTAINER(w), button);
642 gtk_widget_set_tooltip_text(GTK_WIDGET(button),
643 _("Select the background color"));
644 g_object_set_data(G_OBJECT(w), "bg_button", button);
645 g_signal_connect(button, "clicked",
646 G_CALLBACK(option_color_select_callback), NULL);
647 }
648 break;
649
650 case OT_VIDEO_MODE:
651 log_error("Option type %s (%d) not supported yet.",
652 option_type_name(option_type(poption)),
653 option_type(poption));
654 break;
655 }
656
657 option_set_gui_data(poption, w);
658 if (NULL == w) {
659 log_error("Failed to create a widget for option %d \"%s\".",
660 option_number(poption), option_name(poption));
661 } else {
662 g_object_set_data(G_OBJECT(w), "main_widget", ebox);
663 gtk_widget_set_hexpand(w, TRUE);
664 gtk_widget_set_halign(w, GTK_ALIGN_END);
665 gtk_container_add(GTK_CONTAINER(main_hbox), w);
666 }
667
668 gtk_widget_show_all(ebox);
669
670 /* Set as current value. */
672}
673
674/************************************************************************/
677static void option_dialog_option_remove(struct option_dialog *pdialog,
678 struct option *poption)
679{
680 GObject *object = G_OBJECT(option_get_gui_data(poption));
681
682 if (NULL != object) {
683 const int category = option_category(poption);
684
685 option_set_gui_data(poption, NULL);
686 gtk_widget_destroy(GTK_WIDGET(g_object_get_data(object, "main_widget")));
687
688 /* Remove category if needed. */
689 if (0 == --pdialog->box_children[category]) {
690 gtk_notebook_remove_page(GTK_NOTEBOOK(pdialog->notebook), category);
691 pdialog->vboxes[category] = NULL;
692 }
693 }
694}
695
696/************************************************************************/
699static inline void option_dialog_option_bool_set(struct option *poption,
700 bool value)
701{
702 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
703 (option_get_gui_data(poption)),
704 value);
705}
706
707/************************************************************************/
710static inline void option_dialog_option_int_set(struct option *poption,
711 int value)
712{
713 gtk_spin_button_set_value(GTK_SPIN_BUTTON(option_get_gui_data(poption)),
714 value);
715}
716
717/************************************************************************/
720static inline void option_dialog_option_str_set(struct option *poption,
721 const char *string)
722{
723 if (NULL != option_str_values(poption)) {
724 gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN
725 (option_get_gui_data(poption)))), string);
726 } else {
727 gtk_entry_set_text(GTK_ENTRY(option_get_gui_data(poption)), string);
728 }
729}
730
731/************************************************************************/
734static inline void option_dialog_option_enum_set(struct option *poption,
735 int value)
736{
737 GtkComboBox *combo = GTK_COMBO_BOX(option_get_gui_data(poption));
738 GtkTreeModel *model = gtk_combo_box_get_model(combo);
739 GtkTreeIter iter;
740 int i;
741
742 if (gtk_tree_model_get_iter_first(model, &iter)) {
743 do {
744 gtk_tree_model_get(model, &iter, 0, &i, -1);
745 if (i == value) {
746 gtk_combo_box_set_active_iter(combo, &iter);
747 return;
748 }
749 } while (gtk_tree_model_iter_next(model, &iter));
750 }
751
752 log_error("Didn't find the value %d for option \"%s\" (nb %d).",
753 value, option_name(poption), option_number(poption));
754}
755
756/************************************************************************/
759static inline void option_dialog_option_bitwise_set(struct option *poption,
760 unsigned value)
761{
762 GObject *data = option_get_gui_data(poption);
763 GList *iter = g_object_get_data(data, "check_buttons");
764 int bit;
765
766 for (bit = 0; NULL != iter; iter = g_list_next(iter), bit++) {
767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(iter->data),
768 value & (1 << bit));
769 }
770}
771
772/************************************************************************/
775static inline void option_dialog_option_font_set(struct option *poption,
776 const char *font)
777{
778 gtk_font_chooser_set_font(GTK_FONT_CHOOSER
779 (option_get_gui_data(poption)), font);
780}
781
782/************************************************************************/
785static inline void option_dialog_option_color_set(struct option *poption,
786 struct ft_color color)
787{
788 GtkWidget *w = option_get_gui_data(poption);
789 GdkRGBA gdk_color;
790
791 /* Update the foreground button. */
792 if (NULL != color.foreground
793 && '\0' != color.foreground[0]
794 && gdk_rgba_parse(&gdk_color, color.foreground)) {
795 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
796 "fg_button"),
797 &gdk_color);
798 } else {
799 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
800 "fg_button"), NULL);
801 }
802
803 /* Update the background button. */
804 if (NULL != color.background
805 && '\0' != color.background[0]
806 && gdk_rgba_parse(&gdk_color, color.background)) {
807 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
808 "bg_button"),
809 &gdk_color);
810 } else {
811 option_color_set_button_color(g_object_get_data(G_OBJECT(w),
812 "bg_button"), NULL);
813 }
814}
815
816/************************************************************************/
819static void option_dialog_option_refresh(struct option *poption)
820{
821 switch (option_type(poption)) {
822 case OT_BOOLEAN:
824 break;
825 case OT_INTEGER:
827 break;
828 case OT_STRING:
830 break;
831 case OT_ENUM:
833 break;
834 case OT_BITWISE:
836 break;
837 case OT_FONT:
839 break;
840 case OT_COLOR:
842 break;
843 case OT_VIDEO_MODE:
844 log_error("Option type %s (%d) not supported yet.",
845 option_type_name(option_type(poption)),
846 option_type(poption));
847 break;
848 }
849
850 gtk_widget_set_sensitive(option_get_gui_data(poption),
851 option_is_changeable(poption));
852}
853
854/************************************************************************/
857static void option_dialog_option_reset(struct option *poption)
858{
859 switch (option_type(poption)) {
860 case OT_BOOLEAN:
862 break;
863 case OT_INTEGER:
865 break;
866 case OT_STRING:
868 break;
869 case OT_ENUM:
871 break;
872 case OT_BITWISE:
874 break;
875 case OT_FONT:
877 break;
878 case OT_COLOR:
880 break;
881 case OT_VIDEO_MODE:
882 log_error("Option type %s (%d) not supported yet.",
883 option_type_name(option_type(poption)),
884 option_type(poption));
885 break;
886 }
887}
888
889/************************************************************************/
892static void option_dialog_option_apply(struct option *poption)
893{
894 GtkWidget *w = GTK_WIDGET(option_get_gui_data(poption));
895
896 switch (option_type(poption)) {
897 case OT_BOOLEAN:
898 (void) option_bool_set(poption, gtk_toggle_button_get_active
899 (GTK_TOGGLE_BUTTON(w)));
900 break;
901
902 case OT_INTEGER:
903 (void) option_int_set(poption, gtk_spin_button_get_value_as_int
904 (GTK_SPIN_BUTTON(w)));
905 break;
906
907 case OT_STRING:
908 if (NULL != option_str_values(poption)) {
909 (void) option_str_set(poption, gtk_entry_get_text
910 (GTK_ENTRY(gtk_bin_get_child(GTK_BIN(w)))));
911 } else {
912 (void) option_str_set(poption, gtk_entry_get_text(GTK_ENTRY(w)));
913 }
914 break;
915
916 case OT_ENUM:
917 {
918 GtkTreeIter iter;
919 int value;
920
921 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w), &iter)) {
922 break;
923 }
924
925 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(w)),
926 &iter, 0, &value, -1);
927 (void) option_enum_set_int(poption, value);
928 }
929 break;
930
931 case OT_BITWISE:
932 {
933 GList *iter = g_object_get_data(G_OBJECT(w), "check_buttons");
934 unsigned value = 0;
935 int bit;
936
937 for (bit = 0; NULL != iter; iter = g_list_next(iter), bit++) {
938 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(iter->data))) {
939 value |= 1 << bit;
940 }
941 }
942 (void) option_bitwise_set(poption, value);
943 }
944 break;
945
946 case OT_FONT:
947 (void) option_font_set(poption, gtk_font_chooser_get_font
948 (GTK_FONT_CHOOSER(w)));
949 break;
950
951 case OT_COLOR:
952 {
953 gchar *fg_color_text = NULL, *bg_color_text = NULL;
954 GObject *button;
955 GdkRGBA *color;
956
957 /* Get foreground color. */
958 button = g_object_get_data(G_OBJECT(w), "fg_button");
959 color = g_object_get_data(button, "color");
960 if (color) fg_color_text = gdk_rgba_to_string(color);
961
962 /* Get background color. */
963 button = g_object_get_data(G_OBJECT(w), "bg_button");
964 color = g_object_get_data(button, "color");
965 if (color) bg_color_text = gdk_rgba_to_string(color);
966
967 (void) option_color_set(poption,
968 ft_color_construct(fg_color_text, bg_color_text));
969 g_free(fg_color_text);
970 g_free(bg_color_text);
971 }
972 break;
973
974 case OT_VIDEO_MODE:
975 log_error("Option type %s (%d) not supported yet.",
976 option_type_name(option_type(poption)),
977 option_type(poption));
978 break;
979 }
980}
981
982/************************************************************************/
985void option_dialog_popup(const char *name, const struct option_set *poptset)
986{
987 struct option_dialog *pdialog = option_dialog_get(poptset);
988
989 if (NULL != pdialog) {
991 } else {
993 }
994}
995
996/************************************************************************/
1000{
1001 struct option_dialog *pdialog = option_dialog_get(poptset);
1002
1003 if (NULL != pdialog) {
1004 option_dialog_destroy(pdialog);
1005 }
1006}
1007
1008/************************************************************************/
1012static void option_gui_update_extra(struct option *poption)
1013{
1014 if (option_optset(poption) == server_optset) {
1015 if (strcmp(option_name(poption), "aifill") == 0) {
1017 } else if (strcmp(option_name(poption), "nationset") == 0) {
1019 }
1020 }
1021}
1022
1023/************************************************************************/
1026void option_gui_update(struct option *poption)
1027{
1028 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1029
1030 if (NULL != pdialog) {
1032 }
1033
1034 option_gui_update_extra(poption);
1035}
1036
1037/************************************************************************/
1040void option_gui_add(struct option *poption)
1041{
1042 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1043
1044 if (NULL != pdialog) {
1045 option_dialog_option_add(pdialog, poption, TRUE);
1046 }
1047
1048 option_gui_update_extra(poption);
1049}
1050
1051/************************************************************************/
1054void option_gui_remove(struct option *poption)
1055{
1056 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
1057
1058 if (NULL != pdialog) {
1059 option_dialog_option_remove(pdialog, poption);
1060 }
1061}
#define str
Definition astring.c:76
static struct fc_sockaddr_list * list
Definition clinet.c:102
enum event_type event
Definition events.c:81
#define _(String)
Definition fcintl.h:67
static struct ft_color ft_color_construct(const char *foreground, const char *background)
void nationset_sync_to_server(const char *nationset)
Definition dialogs.c:809
GtkWidget * toplevel
Definition gui_main.c:124
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
static struct gui_dialog * shell
Definition messagedlg.c:39
static void option_dialog_destroy_callback(GtkWidget *object, gpointer data)
Definition optiondlg.c:129
static void color_selector_response_callback(GtkDialog *dialog, gint res, gpointer data)
Definition optiondlg.c:306
static struct option_dialog * option_dialog_get(const struct option_set *poptset)
Definition optiondlg.c:228
void option_gui_remove(struct option *poption)
Definition optiondlg.c:1048
static void option_dialog_option_refresh(struct option *poption)
Definition optiondlg.c:813
void option_dialog_popdown(const struct option_set *poptset)
Definition optiondlg.c:993
static void option_dialog_option_color_set(struct option *poption, struct ft_color color)
Definition optiondlg.c:779
static void option_color_set_button_color(GtkButton *button, const GdkRGBA *new_color)
Definition optiondlg.c:255
static void option_dialog_option_add(struct option_dialog *pdialog, struct option *poption, bool reorder_notebook)
Definition optiondlg.c:486
#define option_dialogs_iterate_end
Definition optiondlg.c:55
static void option_dialog_option_bitwise_set(struct option *poption, unsigned value)
Definition optiondlg.c:753
static void option_dialog_destroy(struct option_dialog *pdialog)
Definition optiondlg.c:412
static void option_dialog_option_bool_set(struct option *poption, bool value)
Definition optiondlg.c:693
static void option_dialog_option_remove(struct option_dialog *pdialog, struct option *poption)
Definition optiondlg.c:671
void option_gui_add(struct option *poption)
Definition optiondlg.c:1034
static void option_color_select_callback(GtkButton *button, gpointer data)
Definition optiondlg.c:328
static void option_dialog_option_int_set(struct option *poption, int value)
Definition optiondlg.c:704
static void option_dialog_reponse_callback(GtkDialog *dialog, gint response_id, gpointer data)
Definition optiondlg.c:97
#define option_dialogs_iterate(pdialog)
Definition optiondlg.c:53
static void option_gui_update_extra(struct option *poption)
Definition optiondlg.c:1006
static void option_apply_callback(GtkMenuItem *menuitem, gpointer data)
Definition optiondlg.c:169
static void option_color_destroy_notify(gpointer data)
Definition optiondlg.c:243
static void option_dialog_option_font_set(struct option *poption, const char *font)
Definition optiondlg.c:769
void option_gui_update(struct option *poption)
Definition optiondlg.c:1020
static int option_dialog_pages_sort_func(const void *w1, const void *w2)
Definition optiondlg.c:438
void option_dialog_popup(const char *name, const struct option_set *poptset)
Definition optiondlg.c:979
static void option_dialog_reorder_notebook(struct option_dialog *pdialog)
Definition optiondlg.c:450
static void option_dialog_option_apply(struct option *poption)
Definition optiondlg.c:886
static gboolean option_button_press_callback(GtkWidget *widget, GdkEventButton *event, gpointer data)
Definition optiondlg.c:182
@ RESPONSE_SAVE
Definition optiondlg.c:66
@ RESPONSE_APPLY
Definition optiondlg.c:63
@ RESPONSE_CANCEL
Definition optiondlg.c:61
@ RESPONSE_OK
Definition optiondlg.c:62
@ RESPONSE_RESET
Definition optiondlg.c:64
@ RESPONSE_REFRESH
Definition optiondlg.c:65
static void option_dialog_option_reset(struct option *poption)
Definition optiondlg.c:851
static void option_reset_callback(GtkMenuItem *menuitem, gpointer data)
Definition optiondlg.c:156
static void option_dialog_foreach(struct option_dialog *pdialog, void(*option_action)(struct option *))
Definition optiondlg.c:472
static void option_dialog_option_str_set(struct option *poption, const char *string)
Definition optiondlg.c:714
static struct option_dialog_list * option_dialogs
Definition optiondlg.c:58
static void option_dialog_option_enum_set(struct option *poption, int value)
Definition optiondlg.c:728
static void option_refresh_callback(GtkMenuItem *menuitem, gpointer data)
Definition optiondlg.c:143
void ai_fill_changed_by_server(int aifill)
Definition pages.c:1651
static int opt_dlog_height
Definition optiondlg.c:39
static int opt_dlog_width
Definition optiondlg.c:39
static struct option_dialog * option_dialog_new(void)
Definition optiondlg.c:788
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define log_error(message,...)
Definition log.h:103
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_malloc(sz)
Definition mem.h:34
const struct strvec * option_str_values(const struct option *poption)
Definition options.c:890
unsigned option_bitwise_def(const struct option *poption)
Definition options.c:1060
int option_int_min(const struct option *poption)
Definition options.c:831
bool option_bool_def(const struct option *poption)
Definition options.c:783
const char * option_font_def(const struct option *poption)
Definition options.c:1127
const struct option_set * server_optset
Definition options.c:4009
const char * option_description(const struct option *poption)
Definition options.c:613
const char * option_help_text(const struct option *poption)
Definition options.c:623
struct ft_color option_color_get(const struct option *poption)
Definition options.c:1165
int option_enum_get_int(const struct option *poption)
Definition options.c:955
int option_number(const struct option *poption)
Definition options.c:593
int option_category(const struct option *poption)
Definition options.c:643
bool option_str_set(struct option *poption, const char *str)
Definition options.c:901
const char * option_name(const struct option *poption)
Definition options.c:603
int option_int_get(const struct option *poption)
Definition options.c:809
bool option_color_set(struct option *poption, struct ft_color color)
Definition options.c:1188
bool option_bool_set(struct option *poption, bool val)
Definition options.c:794
bool option_is_changeable(const struct option *poption)
Definition options.c:664
void option_set_gui_data(struct option *poption, void *data)
Definition options.c:742
const char * option_str_get(const struct option *poption)
Definition options.c:868
void * option_get_gui_data(const struct option *poption)
Definition options.c:752
bool option_enum_set_int(struct option *poption, int val)
Definition options.c:1015
bool option_bool_get(const struct option *poption)
Definition options.c:772
int optset_category_number(const struct option_set *poptset)
Definition options.c:432
enum option_type option_type(const struct option *poption)
Definition options.c:633
const char * option_enum_int_to_str(const struct option *poption, int val)
Definition options.c:940
const struct option_set * option_optset(const struct option *poption)
Definition options.c:583
const char * option_str_def(const struct option *poption)
Definition options.c:879
int option_int_max(const struct option *poption)
Definition options.c:842
bool option_font_set(struct option *poption, const char *font)
Definition options.c:1149
void options_save(option_save_log_callback log_cb)
Definition options.c:6053
const struct strvec * option_bitwise_values(const struct option *poption)
Definition options.c:1088
bool option_bitwise_set(struct option *poption, unsigned val)
Definition options.c:1099
const char * option_font_get(const struct option *poption)
Definition options.c:1116
void desired_settable_options_update(void)
Definition options.c:5531
struct ft_color option_color_def(const struct option *poption)
Definition options.c:1176
unsigned option_bitwise_get(const struct option *poption)
Definition options.c:1049
int option_enum_def_int(const struct option *poption)
Definition options.c:979
bool option_int_set(struct option *poption, int val)
Definition options.c:853
const char * option_category_name(const struct option *poption)
Definition options.c:653
int option_int_def(const struct option *poption)
Definition options.c:820
#define options_iterate(poptset, poption)
Definition options.h:527
#define options_iterate_end
Definition options.h:532
#define MAX(x, y)
Definition shared.h:54
const char * strvec_get(const struct strvec *psv, size_t svindex)
size_t strvec_size(const struct strvec *psv)
#define strvec_iterate(psv, str)
#define strvec_iterate_end
Definition colors.h:20
Definition climisc.h:82
int * box_children
Definition optiondlg.c:46
GtkWidget ** vboxes
Definition optiondlg.c:45
GtkWidget * shell
Definition optiondlg.c:43
const struct option_set * poptset
Definition optiondlg.c:42
GtkWidget * notebook
Definition optiondlg.c:44
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47