ADVERT: RMR Software
Please visit the sponsor of this series, and don't forget to say where you heard of them!
3-Lib banner

The Absolute Beginners Guide to OPL

Part 31 - Setting up scrolling


Please ensure you have the latest version (1.7) of the RMREvent program from the RMR web site before reading through this tutorial. If you use an older version, some of the text may not make sense.


From the last session, do you remember using MBMView (or a similar tool) to examine the contents of the RMREvent.mbm image file? Here's roughly what you saw:

Screen shotIn addition to the icon for the toolbar (which we looked at last week), notice 6 of the other 7 images in this MultiBitMap file - don't they look suspiciously like bits of a scrollbar? Well, that's indeed what they are.

There's nothing magical about implementing a scrollbar in an OPL program. Yes, it would have been nice if Psion had provided handy built-in routines to make the process really easy, but several authors have found ways of implementing their own replacements, including RMR's Alan Richey, as here. Let's stop to think for a moment about how a scrollbar should behave:

  1. It should have a thin rectangular area with a marker that slides up and down
  2. The marker's position should represent something happening on the main display, e.g. how far through a set of records the user has got
  3. The marker's size should reflect the size of the set of records, e.g. if there are very many records to view, the marker should be small, indicating its relative size compared to the amount that could be scrolled through. Conversely, if there are only a handful of records to view, the marker should be made much larger within the rectangle, showing that the records shown reflect a large proportion of what's available.
  4. Up and down arrows at the bottom of the area should act as a 'fine tuning' control of the marker's position
  5. When the user taps the pen above the marker position, the previous 'page' of records should be shown in the main display. Vice-versa if tapped below the marker.
  6. The user should be able to drag the marker up or down to dynamically (i.e. in real-time) scroll through the pages of information.

Run up RMREvent again and play with the scrollbar. Notice that RMR haven't bothered handling the size of the scrollbar marker at all, or actually doing anything in the main window (other than reporting what's happening with flashing messages). After all, this is only an example program to get you started. If you can get through everything else here, chances are you can work out the rest for yourself! Notice also that dragging the marker with the pen doesn't do anything. This particular scrollbar behaviour is very difficult to implement in OPL/32 in a real program - even if it were done, the scrolling in the main display would be too slow to be practical.

So, how does RMREvent do the bits that it does? Find the bit of code in the Init: procedure starting with ScrollScn%=

ScrollScn%=gCREATE (Screenwidth%-23,0,23,Screenheight%,0,1)
gBORDER 0
Scrollpos%=100
Setup_Scroll:

Screen shotHere we're just making a new long, thin drawable on the screen, i.e. an area we can draw to. It's set up to start 23 pixels in from the right of the current screen width and extend down by the current screen height. Notice the way the code refers to variables for width and height and doesn't just put in actual numbers. This is done partly so the program will stand more chance of working on future EPOC machines with different size screens and partly because Screenwidth% will vary as the toolbar is removed or reinstated. The figure of 23 pixels is just something that looks about right and mimics the style of the built-in applications. Note also the parameters at the end of the gCREATE command. The zero means that OPL/32 shouldn't make the drawable visible yet (i.e. it's to keep it hidden 'behind' the screen until needed) and the 1 tells OPL to use 4-colour mode graphics for the drawable (the usual default).

gBORDER 0 just draws a simple one-pixel frame round the drawable, with no fancy shadow or effects. Scrollpos%=100 just sets the initial position of the marker, a fairly arbitrary number in this trivial example, but probably set to 0 in a real-life program (where you'd almost always start the user at the first available record in a list etc.)

Setup_Scroll: is called next, so move a few lines down in the source code and examine it:

Screen shotPROC Setup_Scroll:
gUSE Scrollscn%
gAT 1,1 : gFILL 21,Screenheight%-2,1
gAT 0,Screenheight%-44
gCOPY Upid&,0,0,24,24,0
gAT 0,Screenheight%-22
gCOPY Downid&,0,0,24,24,0
gAT 0,Scrollpos%
gCOPY SliderId&,0,0,24,24,0
gVISIBLE ON
ENDP

The purpose of this procedure is to do draw the rest of the scrollbar. The gFILL command just clears any pixels in the scrollbar's rectangle. Upid& and Downid& are two drawables into which the up and down arrow pictures have previously been loaded. Here they're just gCOPYed into the right position at the bottom of the scrollbar area. Switch back to the running RMREvent program if you need to, checking that you understand which bit is being drawn by which line. The final gCOPY is to place the marker (whose image was loaded earlier into drawable SliderId&) in position. Notice again that in this example program the marker's size is set at 24 by 24 pixels. In real life, you might want to set the vertical size of the marker as a variable, perhaps MarkerSize%, which you could vary according to how much information there is available to display.

Finally, gVISIBLE ON is used to make the scrollbar drawable 'appear' in one instant. You should note that learning and using the gVISIBLE and gUPDATE commands are excellent ways to improve the look and feel of your programs by making graphics appear faster and more smoothly.

All that's left to do is detect when the user taps below or above the marker, or on the arrow graphics, and to adjust and redraw the marker position accordingly. If you move down a few screenfuls of code, you should come to the following in the main Pointer_Event: procedure:

ELSEIF Window&=Scrollscn%
 IF Y_Position&<Scrollpos%
  giPRINT "Pen/Pointer is on the scroll window above the slider",1
  Scrollmove:(-30)
 ELSEIF Y_Position&<Screenheight%-44
  giPRINT "Pen/Pointer is on the scroll window below the slider",1
  Scrollmove:(30)
 ELSEIF Y_Position&<Screenheight%-22
  giPRINT "Cursor Up",1
  Scrollmove:(-10)
 ELSE
  giPRINT "Cursor Down",1
  Scrollmove:(10)
 ENDIF
ENDIF

This whole section of code is only checked if a pen event is detected in the ScrollScn% window. Don't worry about the exact sequence of the logic, just note for now that depending on where the user taps the pen, a different value is passed to the Scrollmove: procedure. You won't be surprised to learn that Scrollmove: just adjusts the value in the variable Scrollpos% and then redraws the scrollbar in its entirety:

PROC ScrollMove:(D%)
Scrollpos%=Scrollpos%+D%
IF Scrollpos%>Screenheight%-60
 Scrollpos%=Screenheight%-60
ELSEIF Scrollpos%<0
 Scrollpos%=0
ENDIF
Setup_scroll:
ENDP

Screen shotIn a real-world program, I guess the routines could be made more efficient here by Setup_scroll: only redrawing part of the bar, i.e. the marker, but that's an exercise for another day. Note the check for values less than zero or less than 60 pixels from the screen bottom. These values represent the limits of where the marker is 'allowed' to go on screen, butting it up nicely against the screen top and the start of the arrow graphics.

The behaviour of the main display when scrolled is, of course, up to you. Usually the range of records shown or section of image displayed is adjusted in some sensible fashion. How much functionality you build into your own scrolling routines will depend very much on how complex it needs to be for the program to be useful. A fully professional OPL/32 program should endeavour to make its scroll bars as pretty and as functional as the built-in applications. For a example of how well scrollbars can be done in OPL, take a look at Pelican Software's Logit and Notepad programs.

Happy coding! Next week will see us examining how to set up a professional Series 5 help system.


Go to next lesson | Programming index