Output of toggle_box.c with radioBehavior set to True
As you can see, simply changing this single RowColumn resource completely changes the appearance of all the
ToggleButtons.
12.4 ArrowButtons
An ArrowButton is just like a PushButton, except that it only displays a directional arrow symbol. The arrow can
point up, down, left, or right. Motif provides both widget and gadget versions of the ArrowButton; the associated
header files are <Xm/ArrowB.h> and <Xm/ArrowBG.h>. the source code shows a program that creates four
ArrowButtons, one for each direction. XtSetLanguageProc() is only available in X11R5; there is no
corresponding function in X11R4.
/* arrow.c −− demonstrate the ArrowButton widget.
* Have a Form widget display 4 ArrowButtons in a
* familiar arrangement.
*/
#include <Xm/ArrowBG.h>
#include <Xm/Form.h>
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app;
Widget toplevel, form;
Display *dpy;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
dpy = XtDisplay (toplevel);
/* Rather than listing all these resources in an app−defaults file,
* add them directly to the database for this application only. This
* would be virtually equivalent to hard−coding values, since these
* resources will override any other specified external to this file.
12 Labels and Buttons 12.4 ArrowButtons
331
*/
XrmPutStringResource
(&dpy−>db, "*form*topAttachment", "attach_position");
XrmPutStringResource
(&dpy−>db, "*form*leftAttachment", "attach_position");
XrmPutStringResource
(&dpy−>db, "*form*rightAttachment", "attach_position");
XrmPutStringResource
(&dpy−>db, "*form*bottomAttachment", "attach_position");
form = XtVaCreateWidget ("form", xmFormWidgetClass, toplevel,
XmNfractionBase, 3,
NULL);
XtVaCreateManagedWidget ("arrow1",
xmArrowButtonGadgetClass, form,
XmNtopPosition, 0,
XmNbottomPosition, 1,
XmNleftPosition, 1,
XmNrightPosition, 2,
XmNarrowDirection, XmARROW_UP,
NULL);
XtVaCreateManagedWidget ("arrow2",
xmArrowButtonGadgetClass, form,
XmNtopPosition, 1,
XmNbottomPosition, 2,
XmNleftPosition, 0,
XmNrightPosition, 1,
XmNarrowDirection, XmARROW_LEFT,
NULL);
XtVaCreateManagedWidget ("arrow3",
xmArrowButtonGadgetClass, form,
XmNtopPosition, 1,
XmNbottomPosition, 2,
XmNleftPosition, 2,
XmNrightPosition, 3,
XmNarrowDirection, XmARROW_RIGHT,
NULL);
XtVaCreateManagedWidget ("arrow4",
xmArrowButtonGadgetClass, form,
XmNtopPosition, 2,
XmNbottomPosition, 3,
XmNleftPosition, 1,
XmNrightPosition, 2,
XmNarrowDirection, XmARROW_DOWN,
NULL);
XtManageChild (form);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
the figure shows the output of this program.
12 Labels and Buttons 12.4 ArrowButtons
332
The four ArrowButton directions
The size of the arrow−shaped image is calculated dynamically based on the size of the widget itself. If the widget is
resized for some reason, the directional arrow grows or shrinks to fill the widget. The XmNarrowDirection
resource controls the direction of the arrow displayed by an ArrowButton. This resource may have one of the
following values:
XmARROW_UP
XmARROW_DOWN
XmARROW_LEFT
XmARROW_RIGHT
ArrowButtons are useful if you want to provide redundant interface methods for certain widgets. For example, you
could use ArrowButtons to move the viewport of a ScrolledWindow. Redundancy, when used appropriately, can be an
important part of a graphical user interface. Many users may not adapt well to certain interface controls, such as
PulldownMenus in MenuBars or keyboard accelerators, while they are perfectly comfortable with iconic controls such
as ArrowButtons and PushButtons displaying pixmaps. ArrowButtons are also useful if you want to build your own
interface for an object that is not part of the Motif widget set.
ArrowButton widgets and gadgets work in the same way as PushButtons. ArrowButtons have an
XmNactivateCallback, an XmNarmCallback, an XmNdisarmCallback, and a XmNmultiClick
resource. The callback routines all take a parameter of type XmArrowButtonCallbackStruct, which is defined
as follows:
typedef struct {
int reason;
XEvent *event;
int click_count;
} XmArrowButtonCallbackStruct;
This callback structure is identical to the one used for PushButtons.
ArrowButtons are commonly used to increment and decrement a value, a position, or another type of data by some
arbitrary amount. If the amount being incremented or decremented is sufficiently small in comparison to the total size
of the object, it is convenient for the user if you give her the ability to change the value quickly. For example, we can
emulate the activate callback routine being called continuously when the user holds down the mouse button over an
ArrowButton widget. This functionality is not a feature of the ArrowButton; it is something we have to add ourselves.
To implement this feature, we use an Xt timer as demonstrated in the source code XtSetLanguageProc() is only
available in X11R5; there is no corresponding function in X11R4.
/* arrow_timer.c −− demonstrate continuous callbacks using
12 Labels and Buttons 12.4 ArrowButtons
333
* ArrowButton widgets. Display up and down ArrowButtons and
* attach arm and disarm callbacks to them to start and stop timer
* that is called repeatedly while the button is down. A label
* that has a value changes either positively or negatively
* by single increments while the button is depressed.
*/
#include <Xm/ArrowBG.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/LabelG.h>
XtAppContext app;
Widget label;
XtIntervalId arrow_timer_id;
typedef struct value_range {
int value, min, max;
} ValueRange;
main(argc, argv)
int argc;
char *argv[];
{
Widget w, toplevel, rowcol;
void start_stop();
ValueRange range;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
rowcol = XtVaCreateWidget ("rowcol",
xmRowColumnWidgetClass, toplevel,
XmNorientation, XmHORIZONTAL,
NULL);
w = XtVaCreateManagedWidget ("arrow_up",
xmArrowButtonGadgetClass, rowcol,
XmNarrowDirection, XmARROW_UP,
NULL);
XtAddCallback (w, XmNarmCallback, start_stop, 1);
XtAddCallback (w, XmNdisarmCallback, start_stop, 1);
w = XtVaCreateManagedWidget ("arrow_dn",
xmArrowButtonGadgetClass, rowcol,
XmNarrowDirection, XmARROW_DOWN,
NULL);
XtAddCallback (w, XmNarmCallback, start_stop, −1);
XtAddCallback (w, XmNdisarmCallback, start_stop, −1);
range.value = 0;
range.min = −50;
range.max = 50;
label = XtVaCreateManagedWidget ("label",
xmLabelGadgetClass, rowcol,
XtVaTypedArg, XmNlabelString, XmRString, "0 ", 3,
XmNuserData, &range,
NULL);
XtManageChild (rowcol);
XtRealizeWidget (toplevel);
12 Labels and Buttons 12.4 ArrowButtons
334
XtAppMainLoop (app);
}
/* start_stop is used to start or stop the incremental changes to
* the label's value. When the button goes down, the reason is
* XmCR_ARM and the timer starts. XmCR_DISARM disables the timer.
*/
void
start_stop(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
int incr = (int) client_data;
XmArrowButtonCallbackStruct *cbs =
(XmArrowButtonCallbackStruct *) call_data;
void change_value();
if (cbs−>reason == XmCR_ARM)
change_value (incr, 1 );
else if (cbs−>reason == XmCR_DISARM)
XtRemoveTimeOut (arrow_timer_id);
}
/* change_value is called each time the timer expires. This function
* is also used to initiate the timer. The "id" represents that timer
* ID returned from the last call to XtAppAddTimeOut(). If id == 1,
* the function was called from start_stop(), not a timeout. If the value
* has reached its maximum or minimum, don't restart timer, just return.
* If id == 1, this is the first timeout so make it be longer to allow
* the user to release the button and avoid getting into the "speedy"
* part of the timeouts.
*/
void
change_value(client_data, id)
XtPointer client_data;
XtIntervalId id;
{
ValueRange *range;
char buf[8];
int incr = (int) client_data;
XtVaGetValues (label, XmNuserData, &range, NULL);
if (range−>value + incr > range−>max ||
range−>value + incr < range−>min)
return;
range−>value += incr;
sprintf (buf, "%d", range−>value);
XtVaSetValues (label,
XtVaTypedArg, XmNlabelString, XmRString, buf, strlen(buf),
NULL);
arrow_timer_id =
XtAppAddTimeOut (app, id==1? 500 : 100, change_value, incr);
}
The output of this program is shown in the figure.
12 Labels and Buttons 12.4 ArrowButtons
335

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

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.