From: cek@sdc.boeing.com (Conrad Kimball)
Newsgroups: comp.windows.x.motif
Subject: Re: Scrolled list and label
Date: 12 Aug 92 16:49:10 GMT
Organization: Boeing Computer Services, Seattle, WA

In article <1992Aug8.202713.17115@spectrum.xerox.com>, jarnold@spot.wrc.xerox.com (jeff arnold esc1-318) writes:
|> 
|> Does anyone know how to make a label "scroll" with a scrolled list?
|> Specifically, ...
|> 
|> 	This is a long label
|> 	-------------------------
|> 	| list item #1		||
|> 	| list item #2		||
|> 	| list item #3		||
|> 	| list item #4		||
|> 	-------------------------
|> 	-------------------------
|> 
|>          ^^^
|>       I want to scroll both the scrolled list and the label horizontally.

I call this "coupling" a widget to a scrollbar.  I do this as follows:

1.  Enclose within a form the widget you wish to couple to the scrollbar.
    For a horizontal scrolling effect I use just a left and top attachment
    with an offset of 0 so the visuals don't change.

2.  Install callbacks on the scrollbar for *all* the various scrollbar
    movement callbacks.  (Actually, I only do this for a particular
    callback if that callback already has some existing callback - this
    assumes I'm the last one to be installing callbacks on the scrollbar).

3.  This callback function uses the scrollbar's value and minimum resources
    to determine where the scrollbar is positioned, and uses that answer to
    fiddle with the left offset of the coupled widget.  If the left offset
    goes negative, the form will shift the label to the left and clip it,
    giving a visual appearance of being scrolled.

4.  Install a StructureNotifyMask event handler on the scrollbar, so you
    will be notified whenever the scrollbar resizes.

I've generalized this mechanism into the following set of functions, which
no doubt could be further generalized:

------------------------------

Boolean CoupleWidgetToScrollBar(w, resname, scbw, factor, bias)
Widget w;               widget to couple to scrollbar
String resname;         widget resource name to couple
Widget scbw;            scrollbar widget to couple to
int    factor;          factor to multiply scrollbar value
int    bias;            bias to add to multiplied value

This function allows you to couple any widget resource that has an int
value to the value (position) of a scrollbar slider.  That is, when the
scrollbar is moved, the value of the coupled widget's resource will also
change.  The function value is TRUE if the coupling was successfully
established, else FALSE.

The precise formula used when the scrollbar moves is as follows:

1. Compute relative scrollbar value = nominal value - minimum value.

2. Multiply by factor defined when coupling was established.  This allows
   for scaling and/or sign inversion operations.

3. Add bias defined when coupling was established.

4. Add original value that widget resource had when the coupling was
   established.

5. Set the widget resource to the resultant computed value.

This function maintains an internal table of known couplings in which
it retains the specified coupling parameters, and which is cleaned up
when the coupling is removed, either by DecoupleWidgetFromScrollBar()
or when the scrollbar is destroyed.

BUGS:

Coupling works only for resources of type "int".

Coupling may not work for resources whose original value is a default
value.  Some widgets use special internal default values for some
resources.  The widget shouldn't really make this funny value visible
to others once the widget has been initialized, but some do.  If the
resource still has this funny value when you establish the coupling, it
will totally confuse the coupling process.  A case in point is the
"leftOffset" resource for children of a form widget.  The internal
default value (in Motif 1.0.3 anyway) is -62657, which the form widget
treats as equivalent to 0.  If you want to couple the "leftOffset"
resource to a scrollbar, with an original value of 0 (which is the
behavioral default), then prior to establishing the coupling you must
first set the leftOffset resource to an explicit 0 value.  This can be
done in code or with a resource.

Coupling does not work if the scrollbar's position is changed by means
of XtSetValues() on the scrollbar.  The problem is that the scrollbar
doesn't perform any callbacks in this situation, so the coupling code
never gets a chance to get control.  This situation often arises when
you've established a coupling to a scrollbar that is a component of an
XmScrolledList, and you give the XmList a new list to display.  The
XmList widget resets its scrollbars to their 0 position by doing
XtSetValues() on them.  The result is that the XmList and any widget
that has been coupled to one of the XmList's scrollbars are now out of
synch.  This also happens when you use any of the XmList convenience
routines (XmListSetHorizPos(), XmListSetPos(), etc) to indirectly
manipulate the XmScrolledList scrollbars.  To alleviate this problem
use the SyncWidgetsCoupledToScrollBars() function whenever you plug a
new list into an XmList widget and whenever you use the XmList
convenience functions to manipulate the displayed list.

------------------------------

Boolean DecoupleWidgetFromScrollBar(w, resname)
Widget w;           widget that is already coupled
String resname;     widget resource name already coupled

Decouples a widget/resource pair that has previously been coupled to a
scrollbar.  This restores the resource's original value, and it will no
longer change value when the scrollbar's slider moves.  The function
value is TRUE if the coupling was successfully removed, else FALSE.

------------------------------

void SyncWidgetsCoupledToScrollBars()

Ensures that all widgets that have been coupled to any scrollbar have
their coupled resource values in sync with the state of their respective
scrollbar values.  This is sometimes necessary when the state of the
scrollbar is programmatically changed by means of XtSetValues() on the
scrollbar, either explicitly by your program or implicitly by widgets such
as the XmScrolledList widget.  See discussion in CoupleWidgetToScrollBar()
for further information about when you need to do this synchronization.

--
Conrad Kimball		| Unix Server Tech Services, Boeing Computer Services
cek@sdc.boeing.com	| P.O. Box 24346, MS 7A-35
(206) 865-6410		| Seattle, WA  98124-0346
Newsgroups: comp.windows.x.motif