AN ICON SELECTOR SHELL

Mike McNamara presents a set of procedures to implement on-screen buttons.

As powerful as the Wimp system is, it is also very involved, and often, therefore, ignored when writing small programs. However, it is possible to mimic one feature of the Wimp with relative ease - click-sensitive buttons. The program here does just this. It allows any number of buttons (or icons) to be placed on the screen. When the Select button is clicked, the program works out which icon the pointer is over, and takes appropriate action. In the demonstration program, all that happens is that the icon name is displayed, but obviously you could include the routines in your own programs and use the clicks to perform more complex operations.

ENTERING THE PROGRAM

Start by typing in and saving the listing given below. The demonstration program uses the Wimp's sprites as icons, and therefore these must be saved to disc first using the following two instructions:
SYS "Wimp_BaseOfSprites" TO rom%
SYS "OS_SpriteOp",&10C,rom%,"ICONS"

Finally, before running the program, the RISC OS ColourTrans module must be loaded. To do this insert Applications disc 1 in the drive and enter *MOUNT followed by:
*RMLOAD $.!SYSTEM.MODULES.COLOURS

When the program is run, a number of icons are placed on the screen, as can be seen in the illustration. Clicking on most of these will simply display the icon name and its number. However, clicking on the 'A' icon (as used for the Desktop Task Manager) will cause the program to exit.

USING THE ROUTINES

It is a relatively easy matter to include the icon handling routines in your own programs. The procedure PROCinit defines the screen mode to use, the name of the file containing the icon sprites, and the information describing where to place the icons. The filename and mode in line 1120 can be changed as required. Because the ColourTrans module is used, the program will work in any screen mode, and with any sprite except ones defined using 256 colours. Alternatively, if the sprites will all be in the same mode as the program is running in, then you can delete line 740 and change the &234 to &222 in line 560. This removes the need for ColourTrans to be installed. The string assigned to Button$ in line 1170 determines the position of the icons on the screen. This consists of a number of entries concatenated together, each with the format \<spritename>:<x>,<y>;<i> where spritename is the name of the sprite, x and y are the screen co-ordinates of the lower left-hand corner, and i is the icon number. This number has no significance to the program, but is used to identify clicks on the icon.

Looking at the program should make the syntax of this definition clear. As well as setting up Button$, the value of Number% in line 1160 should be set to the total number of icons. Having executed PROCinit, PROCplace_button must then be called for each icon. This can be seen in lines 100 to 120 of the program.

The main loop of the demonstration program repeatedly reads the mouse state and position, and if Select is pressed calls FNbutton_pressed to find which icon (if any) the pointer is over. This function returns the number of the icon under the pointer, or zero if there is none, and the name of the icon sprite in the variable Sprite$. The program then decodes the icon number, exiting if it is icon number four, but otherwise printing its name and number.

Obviously in your own programs you may want to perform some other processing in the main polling loop, and all that is required is that you check the mouse state regularly, and call FNbutton_pressed if necessary. Similarly, it is easy to make the icons respond to buttons other than Select.

10 REM > ScrButton
20 REM Program Screen button shell
30 REM Version A 1.00
40 REM Author Mike McNamara
50 REM RISC User October 1989
60 REM Program Subject to Copyright
70 :
80 PROCinit
90 REM Demo Program
100 FOR icon%=1 TO Number%
110 PROCplace_button(icon%)
120 NEXT icon%
130 *POINTER 1
140 REPEAT
150 OFF
160 MOUSE mx%,my%,mb%
170 IF mb%=4 THEN
180 Number_Pressed%=FNbutton_pressed(mx%,my%)
190 CASE Number_pressed% OF
200 WHEN 4: END
210 OTHERWISE
220 PRINTTAB(1,1);Sprite$,Number_pressed%
230 ENDCASE
240 ENDIF
250 UNTIL FALSE
260 END
270 :
280 *|--------------------------------
290 REM Button handling procedures
300 DEF PROCplace_button(n%)
310 PROCget_button_info(n%)
320 PROCdecode_details(Name$,x%,y%,bnumber%)
330 PROCplot_button(Name$,x%,y%)
340 ENDPROC
350 :
360 DEF PROCget_button_info(N%)
370 Buttons_Left$=Button$
380 FOR button%=0 TO Number%
390 Button_Info$=LEFT$(Buttons_Left$,INSTR(Buttons_Left$,"\")-1)
400 Buttons_Left$=MID$(Buttons_Left$,LEN(Button_Info$)+2)
410 IF VAL(RIGHT$(Button_Info$,LEN(Button_Info$)-INSTR(Button_Info$,";")))=N% THEN button%=Number%
420 NEXT button%
430 ENDPROC
440 :
450 DEF PROCdecode_details(RETURN Name$,RETURN x%,RETURN y%, RETURN bnumber%)
460 Name$=LEFT$(Button_Info$,INSTR(Button_Info$,":")-1)
470 xy$=LEFT$(Button_Info$,INSTR(Button_Info$,";")-1)
480 xy$=MID$(xy$,INSTR(xy$,":")+1)
490 x%=VAL(LEFT$(xy$,INSTR(xy$,",")))
500 y%=VAL(MID$(xy$,INSTR(xy$,",")+1))
510 bnumber%=VAL(MID$(Button_Info$,INSTR(Button_Info$,";")+1))
520 ENDPROC
530 :
540 DEF PROCplot_button(N$,x%,y%)
550 PROCsinfo(N$,scale%,col%)
560 SYS "OS_SpriteOp",&234,sp%,ptr%,x%,y%,8,scale%,col%
570 ENDPROC
580 :
590 DEF PROCsinfo(N$,scale%,col%)
600 SYS "OS_SpriteOp",&118,sp%,N$ TO ,,ptr%
610 smode%=ptr%!40
620 IF ptr%!32=44 THEN
630 palptr%=0
640 ELSE
650 FOR F%=0 TO 56 STEP 8
660 pal%!(F%/2)=ptr%!(F%+44)
670 NEXT
680 palptr%=pal%
690 ENDIF
700 SYS "OS_ReadModeVariable",-1,11 TO
,,A%:!scale%=A%+1
710 SYS "OS_ReadModeVariable",-1,12 TO
,,A%:scale%!4=A%+1
720 SYS "OS_ReadModeVariable",smode%,1
1 TO ,,A%:scale%!8=A%+1
730 SYS "OS_ReadModeVariable",smode%,1
2 TO ,,A%:scale%!12=A%+1
740 SYS "ColourTrans_SelectTable",smode%,palptr%,-1,-1,col%
750 ENDPROC
760 :
770 DEF FNbutton_pressed(MOUX%,MOUY%)
780 Buttons_Left$=Button$
790 FOR button%=0 TO Number%
800 Button_Info$=LEFT$(Buttons_Left$,INSTR(Buttons_Left$,"\")-1)
810 PROCdecode_details(Name$,x%,y%,bnumber%)
820 IF Name$<>"" THEN
830 SYS "OS_SpriteOp",&128,sp%,Name$ TO ,,,width%,height%
840 PROChit(Name$,x%,y%,MOUX%,MOUY%,bnumber%,width%,height%)
850 ENDIF
860 Buttons_Left$=MID$(Buttons_Left$,LEN(Button_Info$)+2)
870 IF hit% THEN button%=Number%
880 NEXT button%
890 hit%=FALSE
900 =Number_Pressed%
910 :
920 DEF PROChit(N$,X%,Y%,MX%,MY%,BN%,W%,H%)
930 PROCsinfo(N$,scale%,col%)
940 W%=W%*!scale%/scale%!8
950 H%=H%*scale%!4/scale%!12
960 SYS "OS_ReadModeVariable",-1,4 TO ,,A%:W%=W%<<A%
970 SYS "OS_ReadModeVariable",-1,5 TO ,,A%:H%=H%<<A%
980 IF MX%>X% AND MY%>Y% THEN
990 IF MX%<X%+W% AND MY%<Y%+H% THEN
1000 Number_pressed%=BN%
1010 Sprite$=N$
1020 SOUND 1,-15,120,1
1030 hit%=TRUE
1040 REPEAT
1050 MOUSE holdx%,holdy%,holdb%
1060 UNTIL holdb%=0
1070 ENDIF
1080 ENDIF
1090 ENDPROC
1100 :
1110 DEF PROCinit
1120 file$="ICONS":mode%=12
1130 MODE mode%
1140 Number_pressed%=0
1150 Sprite$=""
1160 Number%=7
1170 Button$="\file_fff:200,200;1\floppydisc:400,400;2\error:600,100;3\switcher:1100,50;4\directory:900,800;5\network:9
00,200;6\harddisc:500,900;7\"
1180 hit%=FALSE
1190 X%=OPENIN file$
1200 L%=EXT#X%:CLOSE#X%
1210 DIM pal% 63, col% 15, scale% 15, sp% L%+4:!sp%=L%+4
1220 sp%!8=16:SYS "OS_SpriteOp",&109,sp%
1230 SYS "OS_SpriteOp",&10A,sp%,file$
1240 ENDPROC