Scrollbar OPM Module for EPOC |
Dr. Thomas Tensi Paganinistraße 60, D-81247 München |
This OPM module emulates scrollbars (or sliders) for use in OPL on some EPOC machine. A scrollbar is a user interface object where some subinterval fully contained in another interval is displayed. This subinterval stands for some application range (e.g. consecutive visible lines from some larger text) and is graphically represented by a box (the so-called compartment) within another graphical object.
Fig. 1: Example of a horizontal scrollbar
The position of the compartment (and thus the lower and upper limit of the compartment range) can be changed by a pen event but not the length of the interval or the containing interval (the so-called scrollbar range). This is only possible by a method call. Any repositioning of the compartment is immediately reflected in some change of the underlying application range.
My implementation has the following features and misfeatures:
The following steps have to be performed to make the scrollbar module available:
To use the scrollbar in your own program you have to do the following:
INCLUDE "OPM.omh" INCLUDE "Scrollbar.omh"
LOADM OPM_loader$ OPM_loadModule:("Scrollbar") UNLOADM OPM_loader$ Scrollbar_initMODULE:("myFirstProcedure")
The string parameter for Scrollbar_initMODULE:
is the
name of the first procedure in your program.
Later on we shall see that the scrollbar uses user specific
coordinates specified by calls of Scrollbar_setRanges:
.
When the scrollbar is changed either by a pen or key event or by a
call to Scrollbar_setRanges:
, your registered
procedure will be called. Its parameter will contain the value of
the lower bound of the compartment interval.
Scrollbar_create:
with the following signature:
Scrollbar_create%:
This routine has no parameters and returns a scrollbar object identifier (which must be stored in some integer variable for later use), but it does not display a scrollbar yet! Additional steps are still necessary: the compartment and scrollbar range has to be defined and the geometry of the scrollbar must be set and a listener callback routine has to be associated with this scrollbar.
It is necessary to identify the scrollbar in later routines as you may have several scrollbars open at a time.
You can set this callback routine via
Scrollbar_linkToClient:(listenerProc$)
The only parameter listenerProc$
gives the name of
the procedure to be called whenever this specific scrollbar is
changed by an event or by a call to
Scrollbar_setRanges:
.
If you do not specify any listener then the scrollbar works fine, but it does not do anything useful.
Scrollbar_setGeometry:
which has the following signature:
Scrollbar_setGeometry%:(scrollbar%, isVertical%, x%, y%, thickness%, length%, buttonlength%, minCompartmentLength%, borderWidth%)
The first parameter is the scrollbar affected and the second
parameter tells whether this is a vertical or horizontal
scrollbar. x%
and y%
give the position
of the upper left corner in pixels. thickness%
is the
scrollbar thickness and length%
the length of the
scrollbar's main axis including the buttons (both dimensions in
pixels). Note that it depends on the scrollbar being vertical or
horizontal whether thickness%
is the vertical and
length%
the horizontal extension or vice versa.
buttonLength%
(in pixels) tells the size of one
button along the main scrollbar axis and
minCompartmentLength%
(in pixels) fixes the minimum
size for the compartment . The final parameter
borderWidth%
(in pixels) tells how thick the border
around the scrollbar is. Note that the border goes inward, that
means that the outer size is not affected by the border width.
Hence to set up a vertical scrollbar at (500,0) with a thickness of 25 pixels and a length of 240 pixels you say:
LOCAL scrollbar% scrollbar% = Scrollbar_create%: Scrollbar_linkToClient:(scrollbar%, "myUpdateProc") Scrollbar_setGeometry:(scrollbar%, kTrue%, 500, 0, 25, 240, 25, 20, 1)
Note that the buttons are also 25 pixels long, the compartment will be at least 20 pixels long and the border is 1 pixel wide.
Now to do something useful with your scrollbar an initial call to
Scrollbar_setRanges:
is necessary (see below).
Scrollbar_setRanges:
which has the following signature:
Scrollbar_setRanges:(scrollbar%, low&, high&, min&, max&)
The first parameter tells which scrollbar has to be changed.
low&
and high&
give the lower
and upper values of the compartment range. min&
and max&
give the lower and upper values of the
scrollbar range (both ranges are specified by long integers and in
your own coordinates!).
Some caveat is that you specify intervals which are
semi-open. The scrollbar module assumes that the lower value
specified is part of the interval, but the upper part is not. So
e.g. when you define low&
as 1 and
high&
as 2 the compartment goes from 1 to the
number immediately below 2 (this is about 1.999; mathematicians
will shriek in horror..;-.) or - to be more precise - covers the
interval [1,2[. The same logic applies to the scrollbar
range.
If this sounds to you like the weird mathematicians taking
over, then just remember that you should always give an upper
bound which is one more than you would expect. E.g. when you
display line 25 to 37 of a text with 1386 lines you call
Scrollbar_setRanges:
as follows:
Scrollbar_setRanges:(scrollbar%, 25, 38, 1, 1387)
The reason for this strange decision is that it is more logical. Consider a program displaying one of five pictures selected by a scrollbar. If you set up the scrollbar range as 1 to 5 and the compartment range say 3 to 3 you have a problem: the compartment should have length zero! In my opinion it is more logical to say the scrollbar covers interval [1,6[ and each picture is represented by a semiopen interval of length 1 e.g. by [3,4[. So the compartment length is exactly one fifth of the scrollbar length which should be fine...
Whenever you fiddle around with either geometry or ranges the internal data in the scrollbar is changed but the visual representation s not updated! To do that you must issue a call to
Scrollbar_draw:(scrollbar%)
which visually updates the scrollbar to reflect the internal data.
The reason for this design is that you may have many updates in geometry and ranges and do a redraw only when done. Also draw is optimized to redraw only those parts which are invalid.
Scrollbar_offer%:(windowID%, pointerType&, x%, y%)
The first parameter tells in which window the event has
happened. The second parameter tells whether the event was a pen
down, pen up or pen drag. Finally x%
and
y%
give the position of the pen event. You can take
all the information from the result of a call to
GETEVENT32
. It is identical to the information you
would give to a call of TBarOffer
.
Some further remarks:
Scrollbar_offerKey%:(scrollbar%, keyEvent&)
The first parameter tells which scrollbar should take care of that key event, the second parameter tells which key has been pressed. Note that this routine tells you as its result whether the event has been consumed by the scrollbar or not.
Normally a scrollbar consumes arrow keys parallel to its orientation. For example a horizontal scrollbar reacts on a left arrow key, a right arrow key, a page left key and a page right key. The normal arrow keys increment by ±1, the page keys by the ±compartment length. You can define the keys by calling
Scrollbar_setKeyTracking:(scrollbar%, mode%)
where the mode tells whether no arrow keys are accepted,
horizontal or vertical keys or both or those parallel to the
scrollbar orientation. There are constants with prefix
Scrollbar_keyTracking
in the include file with
meaningful names for the mode. When you don't explicitly set the
key tracking the default is handling of parallel arrow keys.
Sometimes this mechanism does not fit for your
application. Then you will have to handle the keys by yourself and
update the scrollbar via calls to
Scrollbar_setRanges:
. This is also not too
complicated.
E.g. when the compartment range is [12,20[ and the overlap is 1 a page down button will move the compartment range to [19,27[.
You can set the overlap via
Scrollbar_setPageOverlap:(scrollbar%, overlap%)where scrollbar denotes the affected scrollbar and overlap is the integer overlap of the ranges.
You can find out about this via
Scrollbar_isVisible%:(scrollbar%)
Scrollbar_close:(scrollbar%)
The only parameter is the scrollbar identifier (just in case you have more than one scrollbar open).
The scrollbar program is put into the public domain and is
unsupported. If you think there is some bug in the program you can
contact me by electronic mail . Currently I cannot promise an immediate answer or even
any answer at all.
You may modify the source code but you are not allowed to publish the scrollbar code as your own work when the changes are marginal. I don't like being confronted with the new OPL 5 scrollbar module by Fredi Klabuster which is nearly 100% my code.
Nevertheless you may use this code freely and of course you don't have to mention me when the scrollbar is part of your program.
Have fun,Thomas Tensi, August 2001
You can download the scrollbar module for OPL (with source code!) for use in your own programs. A detailed instruction for installation and use is available in the SIS-file as "Scrollbar_Doc". Also a tiny demo test driver is included where you can see how to practically use a scrollbar.