The Scale widget allows the user to input numeric values into a program. An example of the Scale widget is shown in Fig. 12.1.
Fig. 12.1 Output of scale.c
To create a Scale Widget use
XtVaCreateManagedWidget() , with a
xmScaleWidgetClass class pointer or
use XmCreateScale() . Once again a header file,
<Xm/Scale.h>
, needs to be included in all programs using Scale widgets.
The following Scale Widget Resources are typically used:
The application programmer must take care of the input value to the program. In the above a value will still get returned in the integer range and somewhere in the application there must be a division by 100.
The Scale callback can be called for two types of events:
The Scale callback function is standard:
void scale_cbk(Widget w, XtPointer data, XmScaleCallbackStruct *struct)
The structure element value holds the current Scale integer value, and is the only structure element that is really of interest. The scale.c program illustrates this usage.
The program simply brings up a virtual volume Scale (in the context of a virtual amplifier controller). The user changes the value which is caught by a XmNvalueChangedCallback and the current value is interrogated to print a message to standard output.
#include <Xm/Xm.h> #include <Xm/Scale.h> /* Prototype callback */ void scale_cbk(Widget , int , XmScaleCallbackStruct *); main(int argc, char **argv) { Widget top_wid, scale; XmString title; XtAppContext app; top_wid = XtVaAppInitialize(&app, "Scale_eg", NULL, 0, &argc, argv, NULL, NULL); title = XmStringCreateLocalized("Volume"); scale = XtVaCreateManagedWidget("scale", xmScaleWidgetClass, top_wid, XmNtitleString, title, XmNorientation, XmHORIZONTAL, XmNmaximum, 11, XmNdecimalPoints, 0, XmNshowValue, True, XmNwidth, 200, XmNheight, 100, NULL); XtAddCallback(scale,XmNvalueChangedCallback, scale_cbk, NULL); XtRealizeWidget(top_wid); XtAppMainLoop(app); } void scale_cbk(Widget widget, int data, XmScaleCallbackStruct *scale_struct) { if (scale_struct->value < 4) printf("Volume too quiet (%d)\n"); else if (scale_struct->value < 7) printf("Volume Ok (%d)\n"); else if (scale_struct->value < 10) printf("Volume too loud (%d)\n"); else /* Volume == 11 */ printf("Volume VERY Loud (%d)\n"); }
The Motif Style Guide (Chapter 18) suggests that some sort of markers should be used to gauge distance along a Scale. However, no provision is made for this within the Scale widget class in Motif 1.2. Instead, the programmer must assemble this manually. An assortment of labels and tics can be used to provide some sort of visual ruler (Fig. 12.2).
Fig. 12.2 Better Style Scale Output
The Motif program code that achieves this, by placing vertical SeparatorGadgets (``'') at equally spaced intervals, is as follows:
Widget ...,tics[1]; ....... ....... /* label scale axis */ for (i=0; i < 11; ++i ) { XtSetArg(args[0], XmNseparatorType, XmSINGLE_LINE); XtSetArg(args[1], XmNorientation, XmVERTICAL); XtSetArg(args[2], XmNwidth, 10); XtSetArg(args[3], XmNheight, 5); tics[i] = XmCreateSeparatorGadget(scale, "|", args, 4); } XtManageChildren(tics, 11); ........... ...........
Motif 2.O provides a new convenience function XmScaleSetTicks() to allow for an easier configuration of ticks along the Scale widget. The configuration allows for three different sized ticks to be placed at specified regular intervals along the Scale. Each tick mark is actually a SeparatorGadget oriented perpendicular to the Scale's orientation. The function XmScaleSetTicks() takes seven arguments:
If you specify tick marks for a Scale and then change the Scale's orientation then you must remove all the tick marks and then recreate new ones in the correct orientation. This may be achieved by the following method: