Widget scale_w;
int value;
void
XmScaleGetValue (scale_w, value)
Widget scale_w;
int *value;
The advantage of using the Motif convenience routines, rather than the Xt routines, is that the Motif routines
manipulate data in the widget directly, rather than using the set and get methods of the Scale. As a result, there is less
overhead involved, although the added overhead of the Xt methods are negligible.
14.3 Scale Orientation and Movement
A Scale can be either vertical or horizontal and the maximum and minimum values can be on either end of the Scale.
By default, as shown in the examples so far, the Scale is oriented vertically with the maximum on the top and the
minimum on the bottom. The XmN-orientation resource can be set to XmHORIZONTAL to produce a horizontal
Scale. The XmNprocessingDirection resource controls the location of the maximum and minimum values. The
possible values for the resource are:
XmMAX_ON_TOP
XmMAX_ON_BOTTOM
XmMAX_ON_LEFT
XmMAX_ON_RIGHT
Unfortunately, you cannot set the processing direction unless you know the orientation of the Scale, so if you
hard−code one resource, you should set both of them. If the Scale is oriented vertically, the default value is
XmMAX_ON_TOP, but if it is horizontal, the default depends on the value of XmNstringDirection. If you use a
font that is read from right to left, then the maximum value is displayed on the left rather than on the right.
As the user drags the slider, the value of the Scale changes incrementally in the direction of the movement. If the user
clicks the middle mouse button inside the Scale widget, but not on the slider itself, the slider moves to the location of
the click. Unfortunately, in a small Scale widget, the slider takes up a lot of space, so this method provides very poor
control for moving the slider close to its current location.
If the user clicks the left mouse button inside the slider area, but not on the slider itself, the slider moves in increments
determined by the value of XmNscaleMultiple. The value of this resource defaults to the difference between the
maximum and minimum values divided by 10. As of Release 1.2 of the Motif toolkit, you should set
XmNscaleMultiple explicitly if the difference between XmNmaximum and XmNminimum is less than 10.
Otherwise, incremental scaling won't work. For example, a Scale widget whose maximum value is 250 has a scale
increment of 25. If the user presses the left mouse button over the area above or below the slider, the Scale's value
increases of decreases by 25. If the button is held down, the movement continues until the button is released, even if
the slider moves past the location of the pointer.
14.4 Scale Callbacks
The Scale widget provides two callbacks that can be used to monitor the value of the Scale. The
XmNdragCallback callback routines are invoked whenever the user drags the slider. This action does not mean
that the value of the Scale has actually changed or that it will change; it just indicates that the slider is being moved.
The XmNvalueChangedCallback is invoked when the user releases the slider, which results in an actual change
14 The Scale Widget 14.3 Scale Orientation and Movement
371
of the Scale's value. It is possible for the XmNvalueChangedCallback to be called without the
XmNdragCallback having been called. For example, when the user adjusts the Scale using the keyboard or moves
the slider incrementally by clicking in the slider area, but not on the slider itself, only the
XmNvalueChangedCallback is invoked.
These callback routines take the form of an XtCallbackProc, just like any other callback. As with all Motif
callback routines, Motif defines a callback structure for the Scale widget callbacks. The
XmScaleCallbackStruct is defined as follows:
typedef struct {
int reason;
XEvent *event;
int value;
} XmScaleCallbackStruct;
The reason field of this structure is set to XmCR_DRAG or XmCR_VALUE_CHANGED, depending on the action that
invoked the callback. The value field represents the current value of the Scale widget.
the source code shows another example of how the Scale widget can be used. In this case, we create a color previewer
that uses Scales to control the red, green, and blue values of the color that is being edited. This example demonstrates
how the XmNdragCallback can be used to automatically adjust colors as the slider is being dragged. The
XmNvalueChangedCallback is also used to handle the cases where the user adjusts the Scale without dragging
the slider. For a discussion of the Xlib color setting routines used in this program, see Volume One, Xlib
Programming Manual. XtSetLanguageProc() is only available in X11R5; there is no corresponding function in
X11R4.
/* color_slide.c −− Use scale widgets to display the different
* colors of a colormap.
*/
#include <Xm/LabelG.h>
#include <Xm/Scale.h>
#include <Xm/RowColumn.h>
#include <Xm/DrawingA.h>
Widget colorwindow; /* the window the displays a solid color */
XColor color; /* the color in the colorwindow */
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, rowcol, scale;
XtAppContext app;
void new_value();
XtVarArgsList arglist;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
if (DefaultDepthOfScreen (XtScreen (toplevel)) < 2) {
puts ("You must be using a color screen.");
exit (1);
}
color.flags = DoRed | DoGreen | DoBlue;
14 The Scale Widget 14.3 Scale Orientation and Movement
372
/* initialize first color */
XAllocColor (XtDisplay (toplevel),
DefaultColormapOfScreen (XtScreen (toplevel)), &color);
rowcol = XtVaCreateManagedWidget ("rowcol",
xmRowColumnWidgetClass, toplevel, NULL);
colorwindow = XtVaCreateManagedWidget ("colorwindow",
widgetClass, rowcol,
XmNheight, 100,
XmNbackground, color.pixel,
NULL);
/* use rowcol again to create another RowColumn under the 1st */
rowcol = XtVaCreateWidget ("rowcol", xmRowColumnWidgetClass, rowcol,
XmNorientation, XmHORIZONTAL,
NULL);
arglist = XtVaCreateArgsList (NULL,
XmNshowValue, True,
XmNmaximum, 255,
XmNscaleMultiple, 5,
NULL);
scale = XtVaCreateManagedWidget ("Red",
xmScaleWidgetClass, rowcol,
XtVaNestedList, arglist,
XtVaTypedArg, XmNtitleString, XmRString, "Red", 4,
XtVaTypedArg, XmNforeground, XmRString, "Red", 4,
NULL);
XtAddCallback (scale, XmNdragCallback, new_value, DoRed);
XtAddCallback (scale, XmNvalueChangedCallback, new_value, DoRed);
scale = XtVaCreateManagedWidget ("Green",
xmScaleWidgetClass, rowcol,
XtVaNestedList, arglist,
XtVaTypedArg, XmNtitleString, XmRString, "Green", 6,
XtVaTypedArg, XmNforeground, XmRString, "Green", 6,
NULL);
XtAddCallback (scale, XmNdragCallback, new_value, DoGreen);
XtAddCallback (scale, XmNvalueChangedCallback, new_value, DoGreen);
scale = XtVaCreateManagedWidget ("Blue",
xmScaleWidgetClass, rowcol,
XtVaNestedList, arglist,
XtVaTypedArg, XmNtitleString, XmRString, "Blue", 5,
XtVaTypedArg, XmNforeground, XmRString, "Blue", 5,
NULL);
XtAddCallback (scale, XmNdragCallback, new_value, DoBlue);
XtAddCallback (scale, XmNvalueChangedCallback, new_value, DoBlue);
XtFree (arglist);
XtManageChild (rowcol);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
void
new_value(scale_w, client_data, call_data)
14 The Scale Widget 14.3 Scale Orientation and Movement
373
Widget scale_w;
XtPointer client_data;
XtPointer call_data;
{
int rgb = (int) client_data;
XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data;
Colormap cmap = DefaultColormapOfScreen (XtScreen (scale_w));
switch (rgb) {
case DoRed :
color.red = (cbs−>value << 8);
break;
case DoGreen :
color.green = (cbs−>value << 8);
break;
case DoBlue :
color.blue = (cbs−>value << 8);
}
/* reuse the same color again and again */
XFreeColors (XtDisplay (scale_w), cmap, &color.pixel, 1, 0);
if (!XAllocColor (XtDisplay (scale_w), cmap, &color)) {
puts ("Couldn't XAllocColor!");
exit(1);
}
XtVaSetValues (colorwindow, XmNbackground, color.pixel, NULL);
}
The output of this program is shown in the figure. Obviously, a black and white book makes it difficult to show how
this application really looks. However, when you run the program, you should get a feel for using Scale widgets.
Output of color_slide.c
One interesting aspect of the color_slide.c program is the use of XtVaCreateArgsList(). We use this function
to build a single argument list that we use repeatedly. If we didn't use the function, we would have to duplicate the
argument list for each call to XtVaCreateManagedWidget(). The function allocates and returns a pointer to an
object of type XtVarArgsList. This type is an opaque pointer to an array of XtVaTypedArgList objects,
14 The Scale Widget 14.3 Scale Orientation and Movement
374
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.