Using the Toolbox and Basalt to create BASIC applications

Introduction

The combination of the "User Interface Toolbox" (the Toolbox) with the keywords added to BASIC by Basalt provides a rapid method for creating desktop applications that are compact and fast.

There is no need for a special development environment beyond the use of the Toolbox tools and a good editor.

Requirements

This document assumes that you are familiar with BBC BASIC and writing RISC OS applications in general. If you are contemplating programming with the Toolbox you are probably already set up appropriately, but here is a checklist of what is required:

Appendix A has some information about where these resources can be found.

Designing the Interface

The desktop user interface is designed using ResEd and, perhaps, ResTest. This is fully described in the Toolbox manual, and is the same process whatever language you intend to write your program in.

The BasaltApp application has a very simple user interface on which you can build your own interface. Make a copy of !BasaltApp in another directory and then rename it with the name of your new application, eg: !NewApp[1]. During the rename process various references in the application files will be changed to the new name and then the application directory and Resources directory are opened.

Make sure that ResEd has been run or has been 'seen' by the Filer, then double click SELECT on the Res file to load it into ResEd.

The interface has an Iconbar object with an attached IbarMenu with Info and Quit entries. The Quit entry generates user event &82A91 (Quit-Quit) when selected and this is used to quit the task, which will be shown later. Attached to the Info entry is a ProgInfo window and this should be edited so that it shows what you want. The Version can be left unchanged, because it will be updated by the program. There is also a Quit dialogue box object, used by error reporting, and an Alert dialogue box object that can be used to give messages to a user.

Now you need to add and edit objects to make your own program interface, saving the Res file back into the application Resources directory. You can test the way the interface works by dragging the Res file to the ResTest icon on the iconbar.

Many objects and gadgets raise default events, which can be trapped by your program to initiate actions. However, default events can be ambiguous and your program will need code to decide which object they come from. I recommend raising user events when this is possible, because these can be trapped uniquely User event numbers should be greater than &200 and less that &FFFF; use &400 or more for certainty.

If your interface require sprites, these should designed in Paint and the sprites file saved into the Resources directory with the name Sprites, or perhaps Sprites22 for high resolution. To make the sprites appear in ResEd when you are editing the Res file drag the Sprites file to the iconbar icon

When the interface design is complete, load the Messages file in the Resources directory into your editor. Change the text following the Version: token to what you want to appear in the ProgInfo object. You might also want to change the default _TaskName: text.

You can add further token:text lines for information to be used within the program.

Writing the program

Load the application !RunImage file into your editor. It is small, but fully remarked. Here is the essential code:

  • REM> NewApp 0.03 (19 Jan 2012)
  • *BasaltInit
  • ON ERROR ON ERROR OFF:THROW ERROR:END
  • PROCInit
  • ON ERROR PROCError:THROW ERROR
  • POLL
  • PROCQuit
  • END
  • DEFPROCInit
  • REGT @Desktop_ObjectAutoCreated FNCreate
  • REGT @ProgInfo_AboutToBeShown FNVersion
  • REGT @QuitDbox_DialogueCompleted FNQuit[2]
  • INITIALISE "Resources"
  • ENDPROC
  • DEFPROCError
  • OP Quit.Message="Error "+STR$ERR+", "+REPORT$+", at line "+STR$ERL
  • OP Quit.ShowObject(3,0,-1)
  • ENDPROC
  • DEFPROCQuit ENDPROC
  • DEFFNCreate EVAL(BLOCK$(16))=SELF:=0
  • DEFFNVersion OP SELF.Version=TOKEN$("Version"):=0
  • DEFFNQuit=-1

    The first line REM> has the default name and version of your application, which you may wish to change. After the line *BasaltInit, which must not be moved, there is the intitial error handler. After the line POLL is the main error handler, which is multi-tasking. By default these use the Basalt error throwback to your editor, assuming is is compliant. Change THROW ERROR to REPORT ERROR is you want to use Reporter. Use REPORT ERROR EXT to use Reportr's thowback.

    The program is in three parts: initialisation, wimp poll loop and finalisation.

    In PROCInit events are registered against functions to handle them, global variables set up, the Toolbox task initialised and then any post initialisation changes made.

    In PROCQuit any finalisation up is done, such as closing files, before the task exits.

    Registering events

    Events can be Wimp or Toolbox events or wimp user Messages. Each is registered with REGW, REGT or REGM against a function to be called to handle the event. All the Wimp and Toolbox events numbers can be entered as Basalt constants: their names in the manuals prefixed by @. A range of user Messages can be entered in the same way, but must otherwise be entered as numbers.

    The details of these constants can be found under the relevant keyword in the StrongHelp manual, and the Toolbox event names and numbers are also detailed for each class. At runtime, constants are converted to literal numbers, so there is no penalty in using the long names.

    All events that the program may need to respond to must be registered, except user Message 0, Message_Quit, which is handled automatically.

    Initialising the Toolbox

    The keyword INITIALISE takes the name of the application resources directory as a parameter. If the DDEUtils module is present, and it will be for any but the earliest versions of RISC OS 3, then Basalt sets the program Prefix to the !RunImage directory. Therefore only the name Resources is required, but the full pathname could be entered instead.

    In the resources directory there must be a Res file, with the templates for all the objects the program uses, and a Messages file, which must have at least a token _TaskName:. This name will be used by the Task Manager. The Messages file can subsequently be used with the keywords TOKEN, TOKEN$ and TOKENS without further action. There may also be a Sprites file, which will be loaded into a sprites area and will used used by objects. The sprites may also be used by the program with the SPRITES keyword.

    After the task has initialised, TASK returns the task handle, TASK$ the given task name and DIR$ the full pathname of the given resources directory.

    The wimp poll loop

    The keyword POLL enters a wimp poll loop[3]. Events, including Messages, are masked so that only registered events are returned by the wimp[4]. Each returned event is handled by evaluating the registered function. The loop exits if the function returns a value other than 0 or the wimp Message_Quit (0) is received.

    Object attributes

    Each Toolbox object has attributes derived from its class and also from the top-level Desktop class. These are mostly set in the object template when the Res file is created, and some are set by the Toolbox itself. Not all attributes can be both assigned to and evaluated in a program.

    Basalt treats attributes as special types of variables with names identical to the names in the Toolbox manual which are prefixed by Set (assign) and Get (evaluate).

    Basalt allows some of the longer names to have shorter synonyms, and some attributes with multiple values may be split into single attributes. All attribute names are tokenised to a single byte by Basalt, so there is no runtime penalty in the longer names.

    Each class page in the StrongHelp manual shows how the attribute names can be used, but you will need to consult the Toolbox manual for their full meanings.

    A particular object's attribute is written as object.attribute where object is the object handle assigned by the Toolbox and attribute is the attribute name. Gadgets and menu Entries are aggregated components within another object and are referred to by a number. A component attribute is written as object#component.attribute where component is the component number.

    The keyword to use an attribute is OP [5], so:

  • OP ProgInfo.Version="(31-Jan-1999)"
  • version$=OP ProgInfo.Version
  • OP IbarMenu#1.Text="Exit"

    As will be seen later, the handle of the object raising an event is supplied by the Toolbox and this is returned by the keyword SELF, and a component by SELFC, so it is often possible to use this for object:

  • OP SELF.title="New window title"

    Basalt even allows this default handle to be omitted altogether:

  • OP .title="New window title"

    but there must always be a space after OP in this case.

    Attributes with multiple values are evaluated with a different syntax:

    OP Window.Extent TO xmin%,ymin%,xmax%,ymax%

  • Object methods

    Each Toolbox object may be manipulated by methods derived from its class and also from the top-level Desktop class.

    Basalt uses the keyword OP and a very similar syntax for method names to that for attribute names, see above.

    Each class page in the StrongHelp manual shows how the method names can be used, but you will need to consult the Toolbox manual for their full meanings.

    Most methods take parameters enclosed in parentheses, (), and these must be present even if there are no parameters:

  • OP IbarMenu.AddEntry("Choices...",2,0)
  • OP SELF.HideObject()
  • Event handler functions

    An event handler is a BASIC function that is called by the code in the keyword POLL and returns to it. It must return a value of 0, and any other value will cause the loop to end.

    The function can do anything that is normal, including calling other functions and procedures.

    The Toolbox supplies the handles of the object and component raising the event, and also those of the parent to the object and the ancestor of all objects attached above. Basalt returns these handles in SELF, SELFC, PARENT, PARENTC, ANCESTOR and ANCESTORC. These values are not supplied for Wimp and Message events in this version of Basalt.

    Application files

    These are the more-or-less obligatory files in an application in addition to the !RunImage.

    The !Boot file

    This file is run when your application is first 'seen' by the Filer. It sets up the usual directory and path system variables and it will rarely be necessary to change it.

    The !Help file

    This file is run when the user clicks on Help in the Filer menu. It is an obey file that runs a Help file in the Documents directory. You may wish to change it if you are used to programming some other way. There is a line to uncomment that opens the directory if you want the user to have easy access to other documents, such as a StrongHelp manual.

    The !Modules file

    This file is run when the application is launched. It ensures a lot of modules that might be needed to run Toolbox applications. It does not need to be altered, but commented lines may need to be uncommented to use some of Basalt's other keywords and you might want to add other modules.

    The !Run file

    This is fairly standard, but you may wish to add you own commands, and you will have to change the initial Set WimpSlot values unless your program is very small. Basalt can be quite economical with memory and, if you use the dynamic memory with, eg: DIM HIMEM and the LIBRARY function, changes to the wimp slot will be managed for you. A reasonable starting value is 4k plus twice the size of the !RunImage file. If the initial wimp slot is too small there will be 'No Room' or 'Too many nested structures' errors. The most uncertain factor is how much memory is allocated for string variables and this can increase the longer a program runs. Basalt can allocate memory for string variables from dynamic memory with LET, which can alleviate this problem.

    The !Sprites and !Sprites22 files

    These files contain the standard Filer icons for the application in low and high resolutions. You will probably want to edit the spites in Paint to show your own Filer icons rather than the default.

    Application directories

    The organisation of other application files into directories is not standardised, but you may find these convenient.

    Documents

    This contains the Help file, which should be edited so that it tells the user the essential information about the program: what it is for, the licence, who wrote it and where they can be contacted. It may also serve as a manual for some programs, but that might be better in a separate file; a prototype StrongHelp manual is is already included for you to develop. Writing a manual in another proprietary format, such as Word or Impression, might leave the user unable to read it, so you should use a text file or HTML.

    Libraries

    This can be used to hold any supporting libraries for your program.

    Modules

    This contains a copy of the Basalt module, which is a default option. The application should look for a copy in the Basalt application, and a user should be told to obtain/download this and follow the instruction for its installation. There are other modules in the Basalt application that Basalt may use for particular keywords, in which case you will need to edit the !Modules file. You may put other modules for your own application in this directory.

    Resources

    This must contain the Res and Messages files, but may also contain a Sprites[22] file and any other supporting data files. This directory could also contain sub-directories for internationalisation, but that is not covered here. However, the Res file itself can be made international by suffixing the number of a country, so Res1 is the same as Res if the currently configured country is UK. This goes similarly for the Messages file. Further information is in the Toolbox manual.

    Appendix A - Programming resources

    All recent releases of RISC OS, of whatever flavour, will have the Toolbox modules correctly installed. If needed, they can be downloaded from:

    http://www.support.riscos.com/Support/Updates/

    If you are updating an old machine there may be a conflict between ROM versions and soft-loaded versions which is resolved by using UnplugTbox, which is in the Patch for RISC OS download.

    The Toolbox manual is available in the C/C++ development package, which is expensive, or as a PDF (previously restricted) from:

    http://foundation.riscos.com/Private/

    There is an HTML version on the Manuals CD.

    ResEd and ResTest are also available in the C/C++ development package, or from:

    http://www.riscosopen.org/content/downloads/desktop-zipfiles

    Basalt, its StrongHelp manual and the BasaltApp application can be downloaded from:

    http://www.kappa.me.uk/basalt.htm

    There are also several tutorial and example programs.

    Zap can be downloaded from:

    http://zap.tartarus.org

    StrongED can be downloaded from:

    http://www.stronged.iconbar.com

    StrongHelp can be downloaded from:

    http://www.stronged.iconbar.com/fjg/zips/strhlp.zip

    Reporter can be downloaded from:

    http://www.avisoft.force9.co.uk/Reporter.htm

    Undoubtedly there are other places to get these resources and some of them may be more up-to-date.




    [1]  Application names may not be longer than 10 characters if they are to have a sprite.

    [2]  This should be QuitDbox_Quit, but there is a mistake in the module.

    [3]  Basalt also supports a more familiar method of handling events in a CASE structure, but that is not documented here.

    [4]  Some wimp events are not actually masked because they are used by the Toolbox itself.

    [5]  Named for Operation, and derived from the SWI Toolbox_ObjectMiscOp