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>
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>
40 #include "string_vector.h"
49 /* client/gui-gtk-2.0 */
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
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
,
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
90 ****************************************************************************/
91 void toggle_callback(Widget w
, XtPointer client_data
, XtPointer call_data
)
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
102 ****************************************************************************/
103 static void stropt_change_callback(Widget w
, XtPointer client_data
,
106 char *val
= (char *) client_data
;
108 XtVaSetValues(XtParent(XtParent(w
)), "label", val
, NULL
);
111 /****************************************************************************
113 ****************************************************************************/
114 static void option_dialog_ok_callback(Widget w
, XtPointer client_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
,
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
) {
145 } option_dialogs_iterate_end
;
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
,
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. */
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
);
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
);
201 XtVaSetValues(widget
, XtNwidth
, width
, NULL
);
203 if (width
> longest_width
) {
204 longest_width
= width
;
206 } options_iterate_end
;
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
)) {
218 if (NULL
!= widget
) {
219 widget
= XtVaCreateManagedWidget("toggle", toggleWidgetClass
,
220 scrollform
, XtNfromHoriz
,
221 label
, XtNfromVert
, widget
, NULL
);
223 widget
= XtVaCreateManagedWidget("toggle", toggleWidgetClass
,
224 scrollform
, XtNfromHoriz
, label
,
227 XtAddCallback(widget
, XtNcallback
, toggle_callback
, NULL
);
228 option_set_gui_data(poption
, widget
);
231 if (option_str_values(poption
)) {
232 const struct strvec
*vals
= option_str_values(poption
);
235 if (NULL
!= widget
) {
236 widget
= XtVaCreateManagedWidget(option_name(poption
),
237 menuButtonWidgetClass
, scrollform
,
238 XtNfromHoriz
, label
, XtNfromVert
,
241 widget
= XtVaCreateManagedWidget(option_name(poption
),
242 menuButtonWidgetClass
, scrollform
,
243 XtNfromHoriz
, label
, NULL
);
246 popupmenu
= XtVaCreatePopupShell("menu", simpleMenuWidgetClass
,
249 strvec_iterate(vals
, val
) {
250 Widget entry
= XtVaCreateManagedWidget(val
, smeBSBObjectClass
,
252 XtAddCallback(entry
, XtNcallback
, stropt_change_callback
,
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
);
268 /* Else fallthrough. */
270 if (NULL
!= widget
) {
271 widget
= XtVaCreateManagedWidget("input", asciiTextWidgetClass
,
272 scrollform
, XtNfromHoriz
, label
,
273 XtNfromVert
, widget
, NULL
);
275 widget
= XtVaCreateManagedWidget("input", asciiTextWidgetClass
,
276 scrollform
, XtNfromHoriz
, label
,
279 option_set_gui_data(poption
, widget
);
286 log_error("Option type %s (%d) not supported yet.",
287 option_type_name(option_type(poption
)),
288 option_type(poption
));
291 } options_iterate_end
;
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
);
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
);
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
)
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
)) {
353 XtVaSetValues(widget
, XtNstate
, option_bool_get(poption
),
354 XtNlabel
, option_bool_get(poption
) ? _("Yes") : _("No"),
361 fc_snprintf(valstr
, sizeof(valstr
), "%d", option_int_get(poption
));
362 XtVaSetValues(widget
, XtNstring
, valstr
, NULL
);
366 XtVaSetValues(widget
, option_str_values(poption
) ? "label"
367 : XtNstring
, option_str_get(poption
), NULL
);
374 log_error("Option type %s (%d) not supported yet.",
375 option_type_name(option_type(poption
)),
376 option_type(poption
));
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
)) {
396 XtVaGetValues(widget
, XtNstate
, &b
, NULL
);
397 option_bool_set(poption
, b
);
405 XtVaGetValues(widget
, XtNstring
, &dp
, NULL
);
406 if (str_to_int(dp
, &val
)) {
407 option_int_set(poption
, val
);
415 XtVaGetValues(widget
, option_str_values(poption
) ? "label"
416 : XtNstring
, &dp
, NULL
);
417 option_str_set(poption
, dp
);
425 log_error("Option type %s (%d) not supported yet.",
426 option_type_name(option_type(poption
)),
427 option_type(poption
));
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
);
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
));