corresponding get function, XmToggleButtonSetState() determines if its parameter is a widget or gadget
internally, so you can use it on either a ToggleButton widget or a ToggleButton gadget.
XmToggleButtonGadgetSetState() can only be used on a gadget.
One important point to make about ToggleButtons is that, unlike PushButtons and DrawnButtons, the callback is not
typically used to take an action in the application. This point becomes clearer with groups of ToggleButtons, which
are commonly used to set the state of various variables. When the user has set the state as desired, she might tell the
application to apply the settings by clicking on an associated PushButton. For this reason, the callback routine for a
ToggleButton may simply set the state of a global variable; the value can then be used by other application functions.
Of course, like almost every object in Motif, a ToggleButton can be put to many uses. For example, a single
ToggleButton could be used to swap the foreground and background colors of a window as soon as the user selects the
button. An application that controls a CD player could have a Pause button represented by a ToggleButton.
12.3.5 RadioBoxes
When a group of ToggleButtons are used as part of an interface, it is in the form of a RadioBox or a CheckBox. The
primary difference between the two is the selection of the ToggleButtons within. In a RadioBox, only one item may be
selected at a time (analogous to old−style AM car radios). You push one button and the previously set button pops out.
Examples of exclusive settings in a RadioBox might be baud rate settings for a communications program or U.S.
versus European paper sizes in the page setup dialog of a word processing -program.
A RadioBox is implemented using a combination of ToggleButton widgets or gadgets and a RowColumn manager
widget. As discussed in Chapter 8, Manager Widgets, the RowColumn widget is a general−purpose composite widget
that manages the layout of its children. The RowColumn has special resources that allow it to act as a RadioBox for a
group of ToggleButtons.
In a RadioBox, only one of the buttons may be set at any given time. This functionality is enforced by the
RowColumn when the resource XmNradioBehavior is set to True. For true RadioBox effect, the
XmNradioAlwaysOne resource can also be set to tell the RowColumn that one of the ToggleButtons should always
be set. Since you have the freedom to add or delete ToggleButtons from a RowColumn, regardless of their state, if you
are not careful you can violate this aspect of radio behavior. Also, XmNradioBehavior is currently not a
dynamically settable resource. If you want to use it, you should create the RowColumn widget with this resource set.
Setting it using XtVaSetValues() after widget creation may not result in the desired behavior. Whenever
XmNradioBehavior is set, the RowColumn automatically sets the XmNindicatorType resource to
XmONE_OF_MANY and the XmNvisibleWhenOff resource to True for all of its ToggleButton children.
Furthermore, the XmNisHomogeneous resource on the RowColumn is forced to True to ensure that no other kinds
of widgets can be contained in that RowColumn instance.
Motif provides the convenience function XmCreateRadioBox() to automatically create a RowColumn widget that
is configured as a RadioBox. This routine creates a RowColumn widget with XmNisHomogeneous set to True,
XmNentryClass set to xmToggleButtonGadgetClass, XmNradioBehavior set to True, and
XmNpacking set to XmPACK_COLUMN. Keep in mind that unless XmNisHomogeneous is set to True, there is
nothing restricting a RadioBox from containing other classes as well as ToggleButtons. Whether the RowColumn is
homogeneous or not, the toggle behavior is not affected. Although the Motif convenience function sets the
homogeneity, it is not a requirement. Prior to Motif 1.1.1, XmCreateRadioBox() actually set
XmNisHomogeneous to False rather than True, which is a bug. If your code relies on the bug and now breaks,
all you need to do is add code to set XmNisHomogeneous to False when you create your RadioBox. For example,
you might want a RadioBox to contain a Label, or perhaps even some other control area, like a Command widget.
12 Labels and Buttons 12.3.5 RadioBoxes
324
the source code contains a program that creates and uses a RadioBox. XtSetLanguageProc() is only available in
X11R5; there is no corresponding function in X11R4.
/* simple_radio.c −− demonstrate a simple radio box. Create a
* box with 3 toggles: "one", "two" and "three". The callback
* routine prints the most recently selected choice. Maintain
* a global variable that stores the most recently selected.
*/
#include <Xm/ToggleBG.h>
#include <Xm/RowColumn.h>
int toggle_item_set;
void
toggled(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
int which = (int) client_data;
XmToggleButtonCallbackStruct *state =
(XmToggleButtonCallbackStruct *) call_data;
printf ("%s: %s0, XtName (widget), state−>set? "on" : "off");
if (state−>set)
toggle_item_set = which;
else
toggle_item_set = 0;
}
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, radio_box, one, two, three;
XtAppContext app;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
radio_box = XmCreateRadioBox (toplevel, "radio_box", NULL, 0);
one = XtVaCreateManagedWidget ("One",
xmToggleButtonGadgetClass, radio_box, NULL);
XtAddCallback (one, XmNvalueChangedCallback, toggled, 1);
two = XtVaCreateManagedWidget ("Two",
xmToggleButtonGadgetClass, radio_box, NULL);
XtAddCallback (two, XmNvalueChangedCallback, toggled, 2);
three = XtVaCreateManagedWidget ("Three",
xmToggleButtonGadgetClass, radio_box, NULL);
XtAddCallback (three, XmNvalueChangedCallback, toggled, 3);
XtManageChild (radio_box);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
12 Labels and Buttons 12.3.5 RadioBoxes
325
}
The program creates three ToggleButtons inside of a RadioBox. When the user selects one of the buttons, the
previously−set widget is toggled off, and the XmNvalueChangedCallback routine is called. Notice that the
routine is called twice for each selection: the first time to notify that the previously set widget has been turned off, and
the second time to notify that the newly set widget has been turned on. The output of the program is shown in the
figure.
Output of radio_box.c
The global variable toggle_item_set indicates which of the three selections is on. The value of
toggle_item_set is accurate at any given time because it is either set to the most currently selected object or it is
set to 0. In a real application, this global variable would be used to store the state of the buttons, so that other
application functions could reference them.
You should beware of lengthy callback lists, however. If you have more than one function in the callback list for the
ToggleButtons (unlike the situation shown above), the entire list is going to be called twice. A zero value for
toggle_item_set indicates that you are in the first of two phases of the toggling mechanism. In this case, you can
fall through your callback lists, as the list is called again with the value set to the recently selected toggle item.
Motif provides another RadioBox creation routine, XmVaCreateSimpleRadioBox(), for creating simple
RadioBoxes. If a RadioBox only has one callback associated with it and you only need to know which button has been
selected, this routine may be used. The form of the function is:
XmVaCreateSimpleRadioBox(parent, name, button_set, callback, ..., NULL)
Widget parent;
String name;
int button_set;
void *callback;
In addition to the specified parameters, the function also accepts a NULL−terminated list of resource−value pairs that
apply to the RowColumn widget that acts as the RadioBox. You can specify any normal RowColumn resources in this
list, as well as the value XmVaRADIOBUTTON, which is a convenient method for specifying a button that is to be
created inside the RadioBox. This parameter is followed by four additional arguments: a label of type XmString,
a mnemonic of type XmKeySym, an accelerator of type String, and accelerator_text (also of type
XmString) that is used to display the accelerator in the widget. Only the label argument has any effect through
Motif 1.2 and all subreleases. You can use XmVaRADIOBUTTON multiple times in the same call to
XmVaCreateSimpleRadioBox(), so that you can create an entire group of ToggleButtons in one function call.
the source code contains an example of XmVaCreateSimpleRadioBox(). This program is functionally identical
12 Labels and Buttons 12.3.5 RadioBoxes
326
to the previous example. XtSetLanguageProc() is only available in X11R5; there is no corresponding function
in X11R4. XmStringCreateLocalized() is only available in Motif 1.2; XmStringCreateSimple() is the
corresponding function in Motif 1.1.
/* simple_radio.c −− demonstrate a simple radio box by using
* XmVaCreateSimpleRadioBox(). Create a box with 3 toggles:
* "one", "two" and "three". The callback routine prints
* the most recently selected choice.
*/
#include <Xm/RowColumn.h>
void
toggled(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
int which = (int) client_data;
XmToggleButtonCallbackStruct *state =
(XmToggleButtonCallbackStruct *) call_data;
printf ("%s: %s0, XtName (widget), state−>set? "on" : "off");
}
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, radio_box;
XtAppContext app;
XmString one, two, three;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
one = XmStringCreateLocalized ("One");
two = XmStringCreateLocalized ("Two");
three = XmStringCreateLocalized ("Three");
radio_box = XmVaCreateSimpleRadioBox (toplevel, "radio_box",
0, /* the inital choice */
toggled, /* the callback routine */
XmVaRADIOBUTTON, one, NULL, NULL, NULL,
XmVaRADIOBUTTON, two, NULL, NULL, NULL,
XmVaRADIOBUTTON, three, NULL, NULL, NULL,
NULL);
XmStringFree (one);
XmStringFree (two);
XmStringFree (three);
XtManageChild (radio_box);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
12 Labels and Buttons 12.3.5 RadioBoxes
327

Get Volume 6A: Motif Programming Manual now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.