Removed silencing of gtk warning logs from gtk3.22-client.
[freeciv.git] / client / gui-xaw / optiondlg.c
blob6cf83224dd34f689e157e0fdc43898f83d76c174
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 <stdio.h>
19 #include <stdlib.h>
21 #include <X11/Intrinsic.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xaw/Form.h>
24 #include <X11/Xaw/Label.h>
25 #include <X11/Xaw/List.h>
26 #include <X11/Xaw/Command.h>
27 #include <X11/Xaw/MenuButton.h>
28 #include <X11/Xaw/SimpleMenu.h>
29 #include <X11/Xaw/Scrollbar.h>
30 #include <X11/Xaw/SmeBSB.h>
31 #include <X11/Xaw/AsciiText.h>
32 #include <X11/Xaw/Toggle.h>
33 #include <X11/Xaw/Viewport.h>
35 /* utility */
36 #include "fcintl.h"
37 #include "log.h"
38 #include "mem.h"
39 #include "shared.h"
40 #include "string_vector.h"
41 #include "support.h"
43 /* common */
44 #include "events.h"
46 /* client */
47 #include "options.h"
49 /* client/gui-gtk-2.0 */
50 #include "gui_main.h"
51 #include "gui_stuff.h"
53 #include "optiondlg.h"
56 /* The option dialog data. */
57 struct option_dialog {
58 const struct option_set *poptset; /* The option set. */
59 Widget shell; /* The main widget. */
62 #define SPECLIST_TAG option_dialog
63 #define SPECLIST_TYPE struct option_dialog
64 #include "speclist.h"
65 #define option_dialogs_iterate(pdialog) \
66 TYPED_LIST_ITERATE(struct option_dialog, option_dialogs, pdialog)
67 #define option_dialogs_iterate_end LIST_ITERATE_END
69 /* All option dialog are set on this list. */
70 static struct option_dialog_list *option_dialogs = NULL;
72 /* Option dialog main functions. */
73 static struct option_dialog *
74 option_dialog_get(const struct option_set *poptset);
75 static struct option_dialog *
76 option_dialog_new(const char *name, const struct option_set *poptset);
77 static void option_dialog_destroy(struct option_dialog *pdialog);
79 static inline void option_dialog_foreach(struct option_dialog *pdialog,
80 void (*option_action)
81 (struct option *));
83 static void option_dialog_option_refresh(struct option *poption);
84 static void option_dialog_option_apply(struct option *poption);
87 /****************************************************************************
88 Changes the label of the toggle widget to Yes/No depending on the state of
89 the toggle.
90 ****************************************************************************/
91 void toggle_callback(Widget w, XtPointer client_data, XtPointer call_data)
93 Boolean b;
95 XtVaGetValues(w, XtNstate, &b, NULL);
96 XtVaSetValues(w, XtNlabel, b ? _("Yes") : _("No"), NULL);
99 /****************************************************************************
100 Callback to change the entry for a string option that has a fixed list
101 of possible entries.
102 ****************************************************************************/
103 static void stropt_change_callback(Widget w, XtPointer client_data,
104 XtPointer call_data)
106 char *val = (char *) client_data;
108 XtVaSetValues(XtParent(XtParent(w)), "label", val, NULL);
111 /****************************************************************************
112 OK button callback.
113 ****************************************************************************/
114 static void option_dialog_ok_callback(Widget w, XtPointer client_data,
115 XtPointer call_data)
117 struct option_dialog *pdialog = (struct option_dialog *) client_data;
119 option_dialog_foreach(pdialog, option_dialog_option_apply);
120 option_dialog_destroy(pdialog);
123 /****************************************************************************
124 Cancel button callback.
125 ****************************************************************************/
126 static void option_dialog_cancel_callback(Widget w, XtPointer client_data,
127 XtPointer call_data)
129 struct option_dialog *pdialog = (struct option_dialog *) client_data;
131 option_dialog_destroy(pdialog);
134 /****************************************************************************
135 Returns the option dialog which fit the option set.
136 ****************************************************************************/
137 static struct option_dialog *
138 option_dialog_get(const struct option_set *poptset)
140 if (NULL != option_dialogs) {
141 option_dialogs_iterate(pdialog) {
142 if (pdialog->poptset == poptset) {
143 return pdialog;
145 } option_dialogs_iterate_end;
147 return NULL;
150 /****************************************************************************
151 Creates a new option dialog.
152 ****************************************************************************/
153 static struct option_dialog *
154 option_dialog_new(const char *name, const struct option_set *poptset)
156 struct option_dialog *pdialog;
157 Widget form, viewport, command, scrollform, label, widget;
158 Dimension width, longest_width = 0;
160 /* Create the dialog structure. */
161 pdialog = fc_malloc(sizeof(*pdialog));
162 pdialog->poptset = poptset;
163 pdialog->shell = I_T(XtCreatePopupShell("settableoptionspopup",
164 transientShellWidgetClass,
165 toplevel, NULL, 0));
166 /* Append to the option dialog list. */
167 if (NULL == option_dialogs) {
168 option_dialogs = option_dialog_list_new();
170 option_dialog_list_append(option_dialogs, pdialog);
172 form = XtVaCreateManagedWidget("settableoptionsform", formWidgetClass,
173 pdialog->shell, NULL);
174 label = I_L(XtVaCreateManagedWidget("settableoptionslabel",
175 labelWidgetClass, form, NULL));
176 viewport = XtVaCreateManagedWidget("settableoptionsviewport",
177 viewportWidgetClass, form, NULL);
178 scrollform = XtVaCreateManagedWidget("settableoptionsscrollform",
179 formWidgetClass, viewport, NULL);
181 /* Add option labels. */
182 widget = NULL;
183 options_iterate(poptset, poption) {
184 if (NULL != widget) {
185 option_set_gui_data(poption, widget); /* Set previous label. */
187 widget = XtVaCreateManagedWidget("label", labelWidgetClass,
188 scrollform, XtNlabel,
189 option_description(poption),
190 XtNfromVert, widget, NULL);
191 } else {
192 widget = XtVaCreateManagedWidget("label", labelWidgetClass,
193 scrollform, XtNlabel,
194 option_description(poption), NULL);
197 /* The addition of a scrollbar screws things up. There must be a
198 * better way to do this. */
199 XtVaGetValues(widget, XtNwidth, &width, NULL);
200 width += 15;
201 XtVaSetValues(widget, XtNwidth, width, NULL);
203 if (width > longest_width) {
204 longest_width = width;
206 } options_iterate_end;
208 /* Resize label. */
209 XtVaSetValues(label, XtNwidth, longest_width + 15, NULL);
211 /* Add option widgets. */
212 options_iterate(poptset, poption) {
213 widget = option_get_gui_data(poption); /* Get previous label. */
214 option_set_gui_data(poption, NULL);
216 switch (option_type(poption)) {
217 case OT_BOOLEAN:
218 if (NULL != widget) {
219 widget = XtVaCreateManagedWidget("toggle", toggleWidgetClass,
220 scrollform, XtNfromHoriz,
221 label, XtNfromVert, widget, NULL);
222 } else {
223 widget = XtVaCreateManagedWidget("toggle", toggleWidgetClass,
224 scrollform, XtNfromHoriz, label,
225 NULL);
227 XtAddCallback(widget, XtNcallback, toggle_callback, NULL);
228 option_set_gui_data(poption, widget);
229 break;
230 case OT_STRING:
231 if (option_str_values(poption)) {
232 const struct strvec *vals = option_str_values(poption);
233 Widget popupmenu;
235 if (NULL != widget) {
236 widget = XtVaCreateManagedWidget(option_name(poption),
237 menuButtonWidgetClass, scrollform,
238 XtNfromHoriz, label, XtNfromVert,
239 widget, NULL);
240 } else {
241 widget = XtVaCreateManagedWidget(option_name(poption),
242 menuButtonWidgetClass, scrollform,
243 XtNfromHoriz, label, NULL);
246 popupmenu = XtVaCreatePopupShell("menu", simpleMenuWidgetClass,
247 widget, NULL);
249 strvec_iterate(vals, val) {
250 Widget entry = XtVaCreateManagedWidget(val, smeBSBObjectClass,
251 popupmenu, NULL);
252 XtAddCallback(entry, XtNcallback, stropt_change_callback,
253 (XtPointer) val);
254 } strvec_iterate_end;
256 if (0 == strvec_size(vals)) {
257 /* We could disable this if there was just one possible choice,
258 * too, but for values that are uninitialized (empty) this
259 * would be confusing. */
260 XtSetSensitive(widget, FALSE);
263 /* There should be another way to set width of menu button */
264 XtVaSetValues(widget, XtNwidth, 120 ,NULL);
265 option_set_gui_data(poption, widget);
266 break;
268 /* Else fallthrough. */
269 case OT_INTEGER:
270 if (NULL != widget) {
271 widget = XtVaCreateManagedWidget("input", asciiTextWidgetClass,
272 scrollform, XtNfromHoriz, label,
273 XtNfromVert, widget, NULL);
274 } else {
275 widget = XtVaCreateManagedWidget("input", asciiTextWidgetClass,
276 scrollform, XtNfromHoriz, label,
277 NULL);
279 option_set_gui_data(poption, widget);
280 break;
281 case OT_ENUM:
282 case OT_BITWISE:
283 case OT_FONT:
284 case OT_COLOR:
285 case OT_VIDEO_MODE:
286 log_error("Option type %s (%d) not supported yet.",
287 option_type_name(option_type(poption)),
288 option_type(poption));
289 break;
291 } options_iterate_end;
293 /* Add buttons. */
294 command = I_L(XtVaCreateManagedWidget("settableoptionsokcommand",
295 commandWidgetClass, form, NULL));
296 XtAddCallback(command, XtNcallback, option_dialog_ok_callback, pdialog);
298 command = I_L(XtVaCreateManagedWidget("settableoptionscancelcommand",
299 commandWidgetClass, form, NULL));
300 XtAddCallback(command, XtNcallback,
301 option_dialog_cancel_callback, pdialog);
303 XtRealizeWidget(pdialog->shell);
304 xaw_horiz_center(label);
305 XtSetSensitive(main_form, FALSE);
306 xaw_set_relative_position(toplevel, pdialog->shell, 25, 25);
307 XtPopup(pdialog->shell, XtGrabNone);
309 return pdialog;
312 /****************************************************************************
313 Destroys an option dialog.
314 ****************************************************************************/
315 static void option_dialog_destroy(struct option_dialog *pdialog)
317 if (NULL != option_dialogs) {
318 option_dialog_list_remove(option_dialogs, pdialog);
321 options_iterate(pdialog->poptset, poption) {
322 option_set_gui_data(poption, NULL);
323 } options_iterate_end;
325 XtDestroyWidget(pdialog->shell);
326 free(pdialog);
327 XtSetSensitive(main_form, TRUE);
330 /****************************************************************************
331 Do an action for all options of the option dialog.
332 ****************************************************************************/
333 static inline void option_dialog_foreach(struct option_dialog *pdialog,
334 void (*option_action)
335 (struct option *))
337 fc_assert_ret(NULL != pdialog);
339 options_iterate(pdialog->poptset, poption) {
340 option_action(poption);
341 } options_iterate_end;
344 /****************************************************************************
345 Update an option in the option dialog.
346 ****************************************************************************/
347 static void option_dialog_option_refresh(struct option *poption)
349 Widget widget = (Widget) option_get_gui_data(poption);
351 switch (option_type(poption)) {
352 case OT_BOOLEAN:
353 XtVaSetValues(widget, XtNstate, option_bool_get(poption),
354 XtNlabel, option_bool_get(poption) ? _("Yes") : _("No"),
355 NULL);
356 break;
357 case OT_INTEGER:
359 char valstr[64];
361 fc_snprintf(valstr, sizeof(valstr), "%d", option_int_get(poption));
362 XtVaSetValues(widget, XtNstring, valstr, NULL);
364 break;
365 case OT_STRING:
366 XtVaSetValues(widget, option_str_values(poption) ? "label"
367 : XtNstring, option_str_get(poption), NULL);
368 break;
369 case OT_ENUM:
370 case OT_BITWISE:
371 case OT_FONT:
372 case OT_COLOR:
373 case OT_VIDEO_MODE:
374 log_error("Option type %s (%d) not supported yet.",
375 option_type_name(option_type(poption)),
376 option_type(poption));
377 break;
380 XtSetSensitive(widget, option_is_changeable(poption));
383 /****************************************************************************
384 Apply the option change.
385 ****************************************************************************/
386 static void option_dialog_option_apply(struct option *poption)
388 if (option_is_changeable(poption)) {
389 Widget widget = (Widget) option_get_gui_data(poption);
391 switch (option_type(poption)) {
392 case OT_BOOLEAN:
394 Boolean b;
396 XtVaGetValues(widget, XtNstate, &b, NULL);
397 option_bool_set(poption, b);
399 break;
400 case OT_INTEGER:
402 XtPointer dp;
403 int val;
405 XtVaGetValues(widget, XtNstring, &dp, NULL);
406 if (str_to_int(dp, &val)) {
407 option_int_set(poption, val);
410 break;
411 case OT_STRING:
413 XtPointer dp;
415 XtVaGetValues(widget, option_str_values(poption) ? "label"
416 : XtNstring, &dp, NULL);
417 option_str_set(poption, dp);
419 break;
420 case OT_ENUM:
421 case OT_BITWISE:
422 case OT_FONT:
423 case OT_COLOR:
424 case OT_VIDEO_MODE:
425 log_error("Option type %s (%d) not supported yet.",
426 option_type_name(option_type(poption)),
427 option_type(poption));
428 break;
433 /****************************************************************************
434 Popup the option dialog for the option set.
435 ****************************************************************************/
436 void option_dialog_popup(const char *name, const struct option_set *poptset)
438 struct option_dialog *pdialog = option_dialog_get(poptset);
440 if (NULL != pdialog) {
441 option_dialog_foreach(pdialog, option_dialog_option_refresh);
442 } else {
443 (void) option_dialog_new(name, poptset);
447 /****************************************************************************
448 Popdown the option dialog for the option set.
449 ****************************************************************************/
450 void option_dialog_popdown(const struct option_set *poptset)
452 struct option_dialog *pdialog = option_dialog_get(poptset);
454 if (NULL != pdialog) {
455 option_dialog_destroy(pdialog);
459 /****************************************************************************
460 Update the GUI for the option.
461 ****************************************************************************/
462 void option_gui_update(struct option *poption)
464 struct option_dialog *pdialog = option_dialog_get(option_optset(poption));
466 if (NULL != pdialog) {
467 option_dialog_option_refresh(poption);
471 /****************************************************************************
472 Add the GUI for the option.
473 ****************************************************************************/
474 void option_gui_add(struct option *poption)
476 /* We cannot currently insert new option widgets. */
477 option_dialog_popdown(option_optset(poption));
480 /****************************************************************************
481 Remove the GUI for the option.
482 ****************************************************************************/
483 void option_gui_remove(struct option *poption)
485 /* We cannot currently remove new option widgets. */
486 option_dialog_popdown(option_optset(poption));