3-Lib banner

The Absolute Beginners Guide to OPL

Part 19 - Buttons everywhere!


Last week we managed to get MiLo to list on screen all previous sets of generated lottery numbers. A more flexible approach would be to use OPL's dialog functions to construct a small 'browser', with buttons to show the previous number, next number etc.

There's quite a bit of typing, cutting and pasting to do this week, but all in the same procedure. Find the last procedure in the program (listprev:) and add in a new LOCAL variable with:

LOCAL k%

Now go down a few lines and change the WHILE...ENDWH loop to be as follows. Note that the third line, the dTEXT, is very long and probably wrapped in your browser window - just enter it in one long line on your Psion or compatible:

WHILE 1 REM Do loop until exited with ESC or Cancel button
  dINIT "Number archive"
  dTEXT "",gen$(A.num1%,2)+" "+gen$(A.num2%,2)+" "+gen$(A.num3%,2)+" "+gen$(A.num4%,2)+" "+gen$(A.num5%,2)+" "+gen$(A.num6%,2)+" "+gen$(A.num7%,2)+" "+gen$(A.num8%,2)
  dBUTTONS "Previous",%p,"Cancel",27,"Next",%n
  k%=DIALOG
  IF k%=27 OR k%=0
    BREAK
  ELSEIF k%=%p
    IF POS=1
      gIPRINT "Already showing first set of numbers!"
    ELSE
      BACK
    ENDIF
  ELSEIF k%=%n
    NEXT
    IF EOF
      gIPRINT "Already showing last set of numbers!"
      BACK
    ENDIF
  ENDIF
ENDWH

Before we go through the code and explain what's going on, translate and run it so that you can see what I'm talking about:

Screen shot

Quite clever, isn't it? OPL's excellent dialog functions allow us to build quite a slick little function with only a few lines of program code. I'll take you through it, step by step:

You've seen the WHILE 1 construction before. It's simply a way of getting a loop to carry on forever until told to stop. Now come three basic dialog commands. dINIT is needed at the start of every dialog in OPL, as a way of saying 'Here come some dialog line definitions'; we've included the optional title in quotes after dINIT as I think dialogs with titles are just a bit more friendly to the user.

Now to the very long line. As you'll note, it's basically just saying "Print out each number in the current record with a space between each one". The extra "", after dTEXT are needed, it's just the way that the command works (see the OPL manual for further details). Because dTEXT always expects text or character strings to follow it, we've had to convert each number (that we previously just PRINTed) into the right form. The function gen$() is extremely useful in this sort of instance, converting a number to a string of characters, e.g. the number 34 would be converted by gen$(34.0,2) into the string "34" (i.e. the characters "3" and "4"). Note that the "2" in the gen$ brackets is fairly irrelevant here but would be use for decimal (floating point, e.g. 3.56) numbers to indicate how many places we want constructed after the decimal point. As always, character strings can simply be concatenated (added together) with the "+" sign, and I've added an extra space (" ") between each as well, for extra readability.

You'll probably want to do what I did, typing in the first gen$(A.num1%,2)+" "+ and then cutting and pasting the rest, changing the integer in the middle afterwards.

Having displayed the list of numbers in the current record on-screen (within the dialog), the next stage is to provide some controls for moving backwards and forwards in the archive file. dBUTTONS is handy for this sort of thing. If you look at the code, you can guess that there will be a button marked "Previous" that returns the ascii code for "p" when pressed (and indeed needs the user to press the letter "p" on the 3a/3c, which has no touch-screen), a "Cancel" button which returns 27 (the ascii code for the 'escape' key) and a "Next" button which returns the code for "n".

The DIALOG command completes the dialog and displays it on-screen. k% is set to the value of whichever button the user uses to complete the dialog. All we've got to do now is handle the three possible values:

  1. IF k%=27 OR k%=0 Note that I check for zero as well as 27 because pressing the Escape key to exit a dialog always returns zero (instead of the more logical '27' - just one of those things you need to know!). The BREAK command just quits out of the current WHILE loop, which is exactly what we need. Once out of the loop, the program CLOSEs the archive file and returns to the main procedure etc.
  2. IF k%=%p If set to this value, the user must have used the "Previous" button. We use the POS command to check the current record number in the archive file. If it's already at 1, there isn't a previous record to go to, so we just put up an error message and carry on. If it's not 1, we use the BACK command to move the record pointer back one notch, ready for display next time through the WHILE loop.
  3. IF k%=%n If set to this value, the user used "Next" instead. Again, there's a quick check we need to make. We use NEXT to advance the record pointer one notch and then check the EOF (End Of File) command. If it comes up 'true', we know that we were already on the last record in the file and so we put up an error message and move the pointer back again. If EOF is 'false' it's OK to carry on and we leave the record pointer as it is (advanced one notch).

Hopefully this has all made sense. Do experiment with DIALOGs, they're enormously useful and a great time-saver. For example, we could have coded up graphical buttons for the user to tap on and display routines to show the numbers etc, but it would have been quite long-winded. By using OPL's built-in functions as much as possible you'll save yourself much time and effort!

For example, I used dialogs to great time-saving effect in my commercial Team Psion (on Psion's Games arcade). Here's a screenshot showing how I displayed each segment of the starting grid:

Screen shot

Good stuff. Again, I could have coded the screen in long-winded OPL, with a routine to handle the control buttons, but it would have been slower, less elegant and taken 10 times as long to write!

For those whose code has become mistyped or confused, the full program code is available here as milo19.txt.

Happy coding and I'll see you next week!


Go to next lesson | Programming index