ARC PROCEDURE LIBRARY

by Lee Calcraft

This month our procedures automate the process of drawing selection boxes, and of determining which, if any, has been selected by the user.

The procedures which we introduced last month permitted comprehensive polling of the mouse, and checking for the position of the pointer. This month we will complement these with a procedure for drawing sets of coloured selection boxes, each of which may contain text of the user's choice, and a function which will return the number of the currently selected box.

To avoid duplicating information in the procedure which draws the boxes, and the function which polls them, I have used an array to hold all common data. This means that the system is very easy to use. You simply set up one array for each set of selection boxes, then call PROCdrawgrid to draw it, and use FNgetboxno to check which box in the current set the user has chosen.

Table 1. The Elements in a Selection Box Array

0X co-ordinate of base
1Y co-ordinate of base
2Cell width
3Cell height
4No of cells across
5No of cells down
6Total width (calculated)
7Total height (calculated)
8Selection background colour
9Grid line colour
10Text colour
11Text X offset
12Text Y offset

THE ARRAY

Table 1 gives the use to which each of the 13 array elements is put. Each must be set up at the start of the program (as in PROCinitialise in the example), except for elements 6 and 7, which are calculated within the program when the grid is first drawn. The function of each should be more or less self explanatory. The first two are the co-ordinates of the bottom left-hand corner of the selection area. If the first of these, the X co-ordinate, is given as -1, then the selection grid will automatically be centred horizontally (see the lower grid in the accompanying example). The next two co-ordinates are the width and height of a single selection cell. Then comes the number of cells in the X and Y directions, followed by the colour numbers for the background, the selection grid itself, and the text. Finally there are two offsets for the text. These should be adjusted by trial and error to ensure that the text falls symmetrically within a given set of boxes.

PROCdrawgrid

The grid drawing procedure has just two parameters: the name of the array holding the data, and a keyword used to identify the block of text to be used with the grid. If no text is required, then this should be given as a double quote, as with the second grid in the example.

In order to avoid using line number references (which in any case are not permitted when using INSTALLed libraries), I have made use of a special procedure PROCrestore. This will restore any block of data, located by the label passed as a parameter. In the accompanying example, the word "Fruits" identifies the group of four fruits whose names appear in the first menu grid.

FNgetboxno

This function takes three parameters: the X and Y co-ordinates of the pointer at the time of selection, and the name of the array corresponding to the grid that you wish to check. It returns the number of the box selected, or -1 if the pointer is outside the designated area.

To see how the procedure-function pair are used together, take a look at the example. This contains all the code you need, except for the definitions of PROCmousewait and FNpositiond from last month. These should both be appended to this month's program.

When you run the program you will see two different selection grids, one with text, the other without. If you press the Select button, a number will be displayed giving the number of the box under the pointer (or zero if you are not over one of the two grids). Note the way in which the program increments by ten the grid number returned by the second grid. This results in a unique number being returned for each one of the 44 possible choices, and would allow you to use a single CASE statement to deal with any selection made anywhere on the screen.

Because of the use of arrays to hold the data for each selection grid, it is a very simple matter to change any feature of any of the grids. For example, to make the first grid two columns wide, alter area1%(4) from 1 to 2 in PROCinitialise, and add four more words to the data at the end of the program. This is all that you need to do. The selection function does not need to be altered at all. It is even easier to change the position of a box on screen, and almost as easy to add a completely new set of boxes by introducing a third array.

NEXT MONTH we will add a touch of class to our selection screens, and provide a procedure for creating three-dimensional selection boxes.

10 REM >Mse2prcs4d
20 REM Procedure/Function Library
30 REM Version A 0.4
40 REM Author Lee Calcraft
50 REM RISC User May 1989
60 REM Program Subject to Copyright
70 :
80 MODE12:VDU19,0,24,0,192,128
90 ON ERROR REPORT:PRINT" at line ";ERL:ON:END
100 PROCinitialise
110 PRINT"Select to test grids"
120 PRINT"or Menu to quit"
130 PROCdrawgrid(area1%(),"Fruits")
140 PROCdrawgrid(area2%(),"")
150 OFF:*POINTER
160 REPEAT
170 PROCmousewait(-8)
180 IF z%=4 THEN
190 CASE TRUE OF
200 WHEN FNgetboxno(x%,y%,area1%())>0:choice%=FNgetboxno(x%,y%,area1%())
210 WHEN FNgetboxno(x%,y%,area2%())>0:choice%=10+FNgetboxno(x%,y%,area2%())
220 OTHERWISE choice%=0
230 ENDCASE
240 PRINTTAB(0,5);"Selection ";choice%;" "
250 ENDIF
260 UNTIL z%=2
270 ON
280 END
290 ==================================
300 DEFPROCinitialise
310 DIM area1%(12)
320 DIM area2%(12)
330 REM.................First group
340 area1%(0)=140 :REM X coord
350 area1%(1)=500 :REM Y coord
360 area1%(2)=200 :REM Cell width
370 area1%(3)=64 :REM Cell height
380 area1%(4)=1 :REM Cells across
390 area1%(5)=4 :REM Cells down
400 area1%(8)=4 :REM Box bcg blue
410 area1%(9)=7 :REM Box line white
420 area1%(10)=7 :REM White text
430 area1%(11)=16 :REM Text x offset
440 area1%(12)=16 :REM Text y offset
450 REM................Second group
460 area2%(0)=-1 :REM Neg so centre
470 area2%(1)=64
480 area2%(2)=100
490 area2%(3)=64
500 area2%(4)=10
510 area2%(5)=4
520 area2%(8)=1 :REM Red bcg
530 area2%(9)=3 :REM Yellow lines
540 area2%(10)=0 :REM Black text
550 area2%(11)=4
560 area2%(12)=4
570 ENDPROC
580 ==================================
590 DEFFNgetboxno(x%,y%,a%())
600 REM Returns no of selected box
610 REM Counting from top left (=no 1)
620 REM and moving left to right
630 LOCAL ix%,iy%,no%
640 IF FNpositiond(x%,y%,a%(0),a%(1),a%(6),a%(7)) THEN
650 ix%=(x%-a%(0)) DIV a%(2)+1
660 iy%=a%(5)-(y%-a%(1)) DIV a%(3)-1
670 no%=ix%+a%(4)*iy%
680 ELSE no%=-1
690 ENDIF
700 =no%
710 ==================================
720 DEFPROCdrawgrid(a%(),text$)
730 REM Draws simple selection grid
740 LOCAL ix%,iy%,no%
750 a%(6)=a%(2)*a%(4)
760 a%(7)=a%(3)*a%(5)
770 IF a%(0)=-1 THEN a%(0)=(1280-a%(6))DIV 2
780 GCOL a%(8)
790 RECTANGLE FILL a%(0),a%(1),a%(6),a%(7)
800 GCOL a%(9)
810 FOR iy%=a%(1) TO a%(1)+a%(7) STEP a%(3)
820 LINE a%(0),iy%,a%(0)+a%(6),iy%
830 NEXT
840 FOR ix%=a%(0) TO a%(0)+a%(6) STEP a%(2)
850 LINE ix%,a%(1),ix%,a%(1)+a%(7)
860 NEXT
870 IF text$<>"" THEN
880 PROCrestore(text$)
890 VDU5:GCOL a%(10)
900 FOR iy%=a%(1)+a%(7) TO a%(1)+a%(3) STEP -a%(3)
910 FOR ix%=a%(0) TO a%(0)+a%(6)-a%(2) STEP a%(2)
920 MOVE ix%+a%(11),iy%-4-a%(12)
930 READ text$:PRINTtext$
940 NEXT:NEXT
950 VDU4:OFF
960 ENDIF
970 ENDPROC
980 ==================================
990 DEFPROCrestore(label$)
1000 RESTORE
1010 REPEAT:READ a$:UNTIL a$=label$
1020 ENDPROC
1030 ==================================
1040 DATA Fruits
1050 DATA Bananas, Apples, Pears, Pineapples