(3)

NAME
XfwfScrollbar

DESCRIPTION
The scrollbar widget helps the user to view data that is too large to be displayed all at once. They are often used through a ScrolledWindow (see there), where they are put next to and/or below the widget that contains the data. The scrollbar controls which part is visible. By manipulating the scrollbar the user can move (`scroll') the data within the other widget. A scrollbar consists of two arrows placed at each end of a rectangle, either at the top and bottom or at the left and right. The former is called a vertical scrollbar, the latter a horizontal one. A smaller rectangle, called the thumb or slider, is placed within the larger one. It can move up and down (vertical scrollbar) or left/right (horizontal scrollbar). Clicking an arrow moves the data in that direction. Pressing the mouse button on an arrow and holding it, moves the data by small increments as long as the mouse button is down. Dragging the slider moves the data proportionally with the slider, either along with the movement of the mouse, or all at once when the mouse button is released. Pressing the mouse button onthe rectangle outside the slider moves the data in larger increments. The ratio of the slider size to the scroll region size typically corresponds to the relationship between the size of the visible data and the total size of the data. For example, if 10 percent of the data is visible, the slider typically occupies 10 percent of the scroll region. This provides the user with a visual clue to the size of the invisible data. The scrollbar widget can be configured as either horizontal or vertical. It is made up of two XfwfArrow widgets and an XfwfSlider2 widget. Therefore, many of the scrollbar's resources are actually resources for these, nameless, widgets. The scrollbar has the same callback list as the slider.

  Public variables
XfwfScrollbar
Name | Class | Type | Default
XtNvertical | XtCVertical | Boolean | True
XtNscrollCallback | XtCScrollCallback | Callback | NULL
XtNscrollResponse | XtCScrollResponse | XTCallbackProc | scroll_response
XtNinitialDelay | XtCInitialDelay | Cardinal | 500
XtNrepeatDelay | XtCRepeatDelay | Cardinal | 50
XtNincrement | XtCIncrement | Float | "0.05"
XtNscrollbarForeground | XtCScrollbarForeground | Pixel | copy_background
XtNshadow | XtCShadow | Dimension | 2
XtNminsize | XtCMinsize | Dimension | 20

XtNvertical
    The orientation of the scrollbar is set with the vertical resource. True means vertical, False horizontal. This resource may only be set during initialization. Any changes via XtVaSetValues result in a warning and are then ignored.

    Boolean  vertical = True

XtNscrollCallback
    The user can interact with the scrollbar in many ways, but there is only a single callback list: scrollCallback. The callback uses the call_data parameter to pass a pointer to an XfwfScrollInfo structure: struct {XfwfSReason reason; XfwfSFlags flags; float vpos, vsize, hpos, hsize;} The flags field is a bitwise combination of XFWF_VPOS, XFWF_HPOS, XFWF_VSIZE and XFWF_HSIZE. The structure contains a field reason, which can have the following values (there exist other values, but they are not used by the scrollbar): item{-} XfwfSUp: if the user clicked (or holds) the up arrow. item{-} XfwfSLeft: ditto left arrow. item{-} XfwfSDown: ditto down arrow. item{-} XfwfSRight: ditto right arrow. item{-} XfwfSPageUp: ditto area above thumb. item{-} XfwfSPageDown: ditto area below thumb. item{-} XfwfSPageLeft: ditto area left of thumb. item{-} XfwfSPageRight: ditto area right of thumb. item{-} XfwfSDrag: if the user drags the thumb. item{-} XfwfSMove: if the user stops dragging the thumb. The other four fields contain the new position of the thumb, as numbers between 0.0 and 1.0 inclusive. In the case of drag and drop actions, the position and size reflect the thumb's {\m actual} position at the end of the dragging. In the other cases, the position is the {\m suggested} new position. In these latter cases, the callback routine should compute the new position and use a call to the function in the ScrollResponse resource (or, more conveniently, to XfwfSetScrollbar) to update the scrollbar.

    <Callback> XtCallbackList  scrollCallback = NULL

XtNscrollResponse
    The standard way to update the scrollbar is with a call to the function that is knwon as the scrollResponse function. To get a pointer to that function, you should use XtGetValues or XtVaGetValues on the XtNscrollResponse resource. But from an application it might be easier to use the XfwfSetScrollbar convenience function instead. The scrollResponse routine has the same format as a callback procedure. The first argument is a widget, this argument is ignored. The second argument is XtPointer client_data, it must point to the scrollbar that is to be updated. The third argument is XtPointer call_data, it must be a pointer to an XfwfScrollInfo structure (see above).

    XtCallbackProc  scrollResponse = scroll_response

XtNinitialDelay
    When the user presses and then holds the mouse button on an arrow or on an area outside the thumb, the scrollbar waits some milliseconds before it starts repeating the callbacks.

    Cardinal  initialDelay = 500

XtNrepeatDelay
    Between repeated calls to the callback routines, the scrollbar will wait a few milliseconds.

    Cardinal  repeatDelay = 50

XtNincrement
    Some widgets may be simple enough that they can scroll a fixed amount whenever the user clicks on one of the arrow buttons. If that is the case, they can let the scrollbar compute the new position. It will be passed in the XfwfScrollInfo structure as the suggested new position. Any receiver is free to ignore the suggestion, however. The default is to add or subtract 0.05.

    float  increment = <String>"0.05"

XtNscrollbarForeground
    The color of the arrow and the thumb also determines the color of the 3D shadow, at least if shadowScheme is set to XfwfAuto, as it is by default. The default value is determined dynamically, it is copied from the background resource.

    Pixel  scrollbarForeground = <CallProc>copy_background

XtNshadow
    The width of the arrow's and thumb's shadow is by default 2 pixels.

    Dimension  shadow = 2

XtNminsize
    The minimum size of the thumb is by default 20 pixels. It can be set with the minsize resource.

    Dimension  minsize = 20

XtNframeWidth
    The slider and the two arrows frame will be forced to 0 pixels. The only frame is that of the whole scrollbar. The default frame width is changed from 0 to 2.

     frameWidth = 2

XtNframeType
    The default frame type is now XfwfSunken.

     frameType = XfwfSunken
    XfwfBoard
    Name | Class | Type | Default
    XtNabs_x | XtCAbs_x | Int | 0
    XtNrel_x | XtCRel_x | Float | "0.0"
    XtNabs_y | XtCAbs_y | Int | 0
    XtNrel_y | XtCRel_y | Float | "0.0"
    XtNabs_width | XtCAbs_width | Int | 0
    XtNrel_width | XtCRel_width | Float | "1.0"
    XtNabs_height | XtCAbs_height | Int | 0
    XtNrel_height | XtCRel_height | Float | "1.0"
    XtNhunit | XtCHunit | Float | "1.0"
    XtNvunit | XtCVunit | Float | "1.0"
    XtNlocation | XtCLocation | String | NULL
    XfwfFrame
    Name | Class | Type | Default
    XtNcursor | XtCCursor | Cursor | None
    XtNframeType | XtCFrameType | FrameType | XfwfRaised
    XtNframeWidth | XtCFrameWidth | Dimension | 0
    XtNframeOffset | XtCFrameOffset | Dimension | 0
    XtNshadowScheme | XtCShadowScheme | ShadowScheme | XfwfAuto
    XtNlightColor | XtCLightColor | Pixel | XtDefaultBackground
    XtNdarkColor | XtCDarkColor | Pixel | XtDefaultForeground
    XtNlightStipple | XtCLightStipple | Bitmap | NULL
    XtNdarkStipple | XtCDarkStipple | Bitmap | NULL
    XfwfCommon
    Name | Class | Type | Default
    XtNtraversalOn | XtCTraversalOn | Boolean | True
    XtNhighlightThickness | XtCHighlightThickness | Dimension | 2
    XtNhighlightColor | XtCHighlightColor | Pixel | XtDefaultForeground
    XtNhighlightPixmap | XtCHighlightPixmap | Pixmap | None
    XtNnextTop | XtCNextTop | Callback | NULL
    XtNuserData | XtCUserData | Pointer | NULL
    Composite
    Name | Class | Type | Default
    XtNchildren | XtCChildren | WidgetList | NULL
    insertPosition | XtCInsertPosition | XTOrderProc | NULL
    numChildren | XtCNumChildren | Cardinal | 0
    Core
    Name | Class | Type | Default
    XtNx | XtCX | Position | 0
    XtNy | XtCY | Position | 0
    XtNwidth | XtCWidth | Dimension | 0
    XtNheight | XtCHeight | Dimension | 0
    borderWidth | XtCBorderWidth | Dimension | 0
    XtNcolormap | XtCColormap | Colormap | NULL
    XtNdepth | XtCDepth | Int | 0
    destroyCallback | XtCDestroyCallback | XTCallbackList | NULL
    XtNsensitive | XtCSensitive | Boolean | True
    XtNtranslations | XtCTranslations | XTTranslations | NULL
    ancestorSensitive | XtCAncestorSensitive | Boolean | False
    accelerators | XtCAccelerators | XTTranslations | NULL
    borderColor | XtCBorderColor | Pixel | 0
    borderPixmap | XtCBorderPixmap | Pixmap | NULL
    background | XtCBackground | Pixel | 0
    backgroundPixmap | XtCBackgroundPixmap | Pixmap | NULL
    mappedWhenManaged | XtCMappedWhenManaged | Boolean | True
    XtNscreen | XtCScreen | Screen * | NULL

  Exports
The XfwfSetScrollbar convenience function can be used to set the position and size of a scrollbar. The two arguments must be between 0.0 and 1.0 (inclusive).
XfwfSetScrollbar( $, double  pos, double  size)
{
    if (! XtIsSubclass($, xfwfScrollbarWidgetClass))
    XtError("XfwfSetScrollbar called with incorrect widget type");
    if (pos < 0.0 || pos > 1.0 || size < 0.0 || size > 1.0)
    XtError("XfwfSetScrollbar called with incorrect arguments");
    if ($vertical) {
    XfwfResizeThumb($slider, 1.0, size);
    XfwfMoveThumb($slider, 0.0, pos);
    } else {
    XfwfResizeThumb($slider, size, 1.0);
    XfwfMoveThumb($slider, pos, 0.0);
    } }

  Actions

Scroll
    The following action is not used by default, but it is defined here, because someone might want to bind it to keys. For example, the subclasses XfwfVScrollbar and XfwfHScrollbar do that.
    void Scroll($, XEvent* event, String* params, Cardinal* num_params)
    {
        XfwfScrollInfo info;
        XfwfGetThumb($slider, info);
        info.reason = XfwfCvtStringToScrollReason(params[0]);
        switch (info.reason) {
        case XfwfSUp:
    	info.flags = XFWF_VPOS;
    	info.vpos = max(0.0, info.vpos - $increment);
    	break;
        case XfwfSDown:
    	info.flags = XFWF_VPOS;
    	info.vpos = min(1.0, info.vpos + $increment);
    	break;
        case XfwfSLeft:
    	info.flags = XFWF_HPOS;
    	info.hpos = max(0.0, info.hpos - $increment);
    	break;
        case XfwfSRight:
    	info.flags = XFWF_HPOS;
    	info.hpos = min(1.0, info.hpos + $increment);
    	break;
        case XfwfSPageUp:
    	info.flags = XFWF_VPOS;
    	info.vpos = max(0.0, info.vpos - info.vsize);
    	break;
        case XfwfSPageDown:
    	info.flags = XFWF_VPOS;
    	info.vpos = min(1.0, info.vpos + info.vsize);
    	break;
        case XfwfSPageLeft:
    	info.flags = XFWF_HPOS;
    	info.hpos = max(0.0, info.hpos - info.hsize);
    	break;
        case XfwfSPageRight:
    	info.flags = XFWF_HPOS;
    	info.hpos = min(1.0, info.hpos + info.hsize);
    	break;
        case XfwfSTop:
    	info.flags = XFWF_VPOS;
    	info.vpos = 0.0;
    	break;
        case XfwfSBottom:
    	info.flags = XFWF_VPOS;
    	info.vpos = 1.0;
    	break;
        case XfwfSLeftSide:
    	info.flags = XFWF_HPOS;
    	info.hpos = 0.0;
    	break;
        case XfwfSRightSide:
    	info.flags = XFWF_HPOS;
    	info.hpos = 1.0;
    	break;
        default: break;				/* Not understood */
        }
        XtCallCallbackList($, $scrollCallback, info);
    }

Importss
incl
 <Xfwf/Arrow.h>
incl
 <Xfwf/Slider2.h>
incl
 <stdio.h>

  Private variables
The three children of the scrollbar are stored in private variables.

Widget  arrow1
Widget  arrow2
Widget  slider
During the initialize method, the variable initializing will be True, so that insert_child can check whether a child should be inserted or not.

Boolean  initializing
The scrollResponse function of the Slider2 that implements the thumb is stored in a private variable.

XtCallbackProc  slider_scroll

  Methods
The initialize method creates the three widgets that make up the scrollbar: two arrows and a slider. It sets the resources of these widgets and redirects the callbacks.
initialize(Widget  request, $, ArgList  args, Cardinal * num_args)
{
    Position x, y, xa2, xslider, ya2, yslider;
    Dimension w, h, wa, ha, wslider, hslider;
    $initializing = True;
    $compute_inside($, x, y, w, h);
    if ($vertical) {
	ha = wa = wslider = w;
	xa2 = xslider = x;
	hslider = (h - 2*ha > 0) ? h - 2*ha : 10;
	yslider = y + ha;
	ya2 = yslider + hslider;
    } else {
	wa = ha = hslider = h;
	ya2 = yslider = y;
	wslider = (w - 2*wa > 0) ? w - 2*wa : 10;
	xslider = x + wa;
	xa2 = xslider + wslider;
    }
    $arrow1 = XtVaCreateManagedWidget
	("_arrow1", xfwfArrowWidgetClass, $,
	 XtNx, x,
	 XtNy, y,
	 XtNwidth, wa,
	 XtNheight, ha,
	 XtNframeWidth, 0,
	 XtNforeground, $scrollbarForeground,
	 XtNinitialDelay, $initialDelay,
	 XtNrepeatDelay, $repeatDelay,
	 XtNtraversalOn, False,
	 XtNhighlightThickness, 0,
	 XtNdirection, $vertical?XfwfTop:XfwfLeft,
	 XtNframeOffset, 0,
	 XtNborderWidth, 0,
	 NULL);
    XtAddCallback($arrow1, XtNcallback, up, $);
    $arrow2 = XtVaCreateManagedWidget
	("_arrow2", xfwfArrowWidgetClass, $,
	 XtNx, xa2,
	 XtNy, ya2,
	 XtNwidth, wa,
	 XtNheight, ha,
	 XtNframeWidth, 0,
	 XtNforeground, $scrollbarForeground,
	 XtNinitialDelay, $initialDelay,
	 XtNrepeatDelay, $repeatDelay,
	 XtNtraversalOn, False,
	 XtNhighlightThickness, 0,
	 XtNdirection, $vertical?XfwfBottom:XfwfRight,
	 XtNframeOffset, 0,
	 XtNborderWidth, 0,
	 NULL);
    XtAddCallback($arrow2, XtNcallback, down, $);
    $slider = XtVaCreateManagedWidget
	("_slider", xfwfSlider2WidgetClass, $,
	 XtNx, xslider,
	 XtNy, yslider,
	 XtNwidth, wslider,
	 XtNheight, hslider,
	 XtNthumbColor, $scrollbarForeground,
	 XtNframeWidth, 0,
	 XtNinitialDelay, $initialDelay,
	 XtNrepeatDelay, $repeatDelay,
	 XtNtraversalOn, False,
	 XtNhighlightThickness, 0,
	 XtNframeOffset, 0,
	 XtNborderWidth, 0,
	 NULL);
    XtAddCallback($slider, XtNscrollCallback, thumbscroll, $);
    XtVaGetValues($slider, XtNscrollResponse, $slider_scroll, NULL);
    $initializing = False;
}
When the scrollbar is resized, the children must be resized also.
resize($)
{
    Position x, y, xa2, xslider, ya2, yslider;
    Dimension w, h, wa, ha, wslider, hslider;
    $compute_inside($, x, y, w, h);
    if ($vertical) {
	wa = wslider = w;
	xa2 = xslider = x;
	ha = 2 * (wa + 1)/3;
	hslider = (h - 2*ha > 0) ? h - 2*ha : 10;
	yslider = y + ha;
	ya2 = yslider + hslider;
    } else {
	ha = hslider = h;
	ya2 = yslider = y;
	wa = 2 * (ha + 1)/3;
	wslider = (w - 2*wa > 0) ? w - 2*wa : 10;
	xslider = x + wa;
	xa2 = xslider + wslider;
    }
    XtConfigureWidget($arrow1, x, y, wa, ha, 0);
    XtConfigureWidget($arrow2, xa2, ya2, wa, ha, 0);
    XtConfigureWidget($slider, xslider, yslider, wslider, hslider, 0);
}
insert_child is redefined here only to be able to give a warning when a child is inserted beyond the three that are created in the initialize method.
insert_child(Widget  child)
{
    if ($initializing)
	#insert_child(child);
    else {
	char s[500];
	(void)sprintf(s, "Cannot add children to a scrollbar (\"%s\"->\"%s\")",
		      XtName(child), XtName($));
	XtWarning(s);
    }
}
The set_values method passes resource values on to the three children.
Boolean  set_values(Widget  old, Widget  request, $, ArgList  args, Cardinal * num_args)
{
    if ($old$vertical != $vertical) {
	XtWarning("Cannot change the \"vertical\" resource of a scrollbar\n");
	$vertical = $old$vertical;
    }
    if ($old$scrollbarForeground != $scrollbarForeground) {
	XtVaSetValues($slider, XtNthumbColor, $scrollbarForeground, NULL);
	XtVaSetValues($arrow1, XtNforeground, $scrollbarForeground, NULL);
	XtVaSetValues($arrow2, XtNforeground, $scrollbarForeground, NULL);
    }
    if ($old$shadow != $shadow) {
	XtVaSetValues($slider, XtNthumbFrameWidth, $shadow, NULL);
	XtVaSetValues($arrow1, XtNarrowShadow, $shadow, NULL);
	XtVaSetValues($arrow2, XtNarrowShadow, $shadow, NULL);
    }
    if ($old$minsize != $minsize) {
	XtVaSetValues($slider, XtNminsize, $minsize, NULL);
    }
    return False;
}
The scroll_response method is accessed via the scrollResponse resource. It is passed the scrollbar itself as the client_data argument and a pointer to an XfwfScrollInfo record as call_data. The scrollbar passes on the call to the Slider2 widget that is managing the thumb.
scroll_response(Widget  wdg, XtPointer  client_data, XtPointer  call_data)
{
    Widget $ = (Widget) client_data;
    $slider_scroll(wdg, $slider, call_data);
}

Utilities
char  rcsid[] = "$Header: Scrollbar.w,v 1.1 92/11/02 14:08:00 bert Exp $"
The up routine is a callback for the first arrow. It invokes the scrollbar's callback.
up(Widget  arrow, XtPointer  client_data, XtPointer  call_data)
{
    Widget $ = (Widget) client_data;
    XfwfScrollInfo info;
    XfwfGetThumb($slider, info);
    if ($vertical) {
	info.reason = XfwfSUp;
	info.flags = XFWF_VPOS;
	info.vpos = max(0.0, info.vpos - $increment);
    } else {
	info.reason = XfwfSLeft;
	info.flags = XFWF_HPOS;
	info.hpos = max(0.0, info.hpos - $increment);
    }
    XtCallCallbackList($, $scrollCallback, info);
}
The down routine is the callback for the second arrow. It invokes the scrollbar's callback.
down(Widget  arrow, XtPointer  client_data, XtPointer  call_data)
{
    Widget $ = (Widget) client_data;
    XfwfScrollInfo info;
    XfwfGetThumb($slider, info);
    if ($vertical) {
	info.reason = XfwfSDown;
	info.flags = XFWF_VPOS;
	info.vpos = min(1.0, info.vpos + $increment);
    } else {
	info.reason = XfwfSRight;
	info.flags = XFWF_HPOS;
	info.hpos = min(1.0, info.hpos + $increment);
    }
    XtCallCallbackList($, $scrollCallback, info);
}
The thumbscroll routine is the callback for the scroll callback of the slider. It invokes the scrollbar's scrollCallback, after making sure that only appropriate position information is passed. (The Slider2 might pass horizontal position where only vertical position is relevant, and vice versa.)
thumbscroll(Widget  w, XtPointer  client_data, XtPointer  call_data)
{
    Widget $ = (Widget) client_data;
    XfwfScrollInfo *info = (XfwfScrollInfo*) call_data;
    if ($vertical)
	info->flags = XFWF_VPOS;
    else
	info->flags = XFWF_HPOS;
    XtCallCallbackList($, $scrollCallback, info);
}
The copy_background routine is resource default procedure. It is called to initialize the default value of the foreground resource.
copy_background($, int  offset, XrmValue * value)
{
    value->addr = (XtPointer) $background_pixel;
}