The overall design of the desktop environment within this version of Archimedes has advanced considerably from Arthur 1.20. Here are various notes about how the facilities should be used, and the principles that shaped their design.
These notes are of interest to ALL applications authors. Some authors may feel that they are not interested in window systems and that they are not appropriate to their particular application. The functionality and usefulness of the RISC OS desktop is such, however, that they will soon find most of their users spending most of their time within the desktop environment. Thus it will have a considerable influence on what typical users understand.
CONSISTENCY. What the multi-tasking Wimp emphasises is that applications work *together* for the user of the machine:
They cooperate in sharing the machine.
They look harmonious.
Their user interfaces are similar.
The whole is more important than a single application.
When porting applications into the desktop environment, check that they work well with the existing applications and utilities. Strive to ensure that the habitual user of the desktop environment and the Welcome Suite applications will find your program easy to use, and natural to learn.
QUALITY. It is much better to write a small program that does something simple, and does it well, than a sprawling mass that crashes occasionally.
RESPONSIVENESS. Archimedes is an extremely fast machine, and this speed can be used to make the machine easier to use and more productive. The system software has been written very carefully so that all of this performance is delivered to be used by the application, rather than being swallowed up within the operating system. Fast, smooth scrolling and redraw are worth striving for as they make effective and productive use of an application much easier.
COLOUR. Covering a wide range of screen modes can seem troublesome when constructing an application, but allows a wide price-range for the end user, who can choose between resolution and cost. Animated bright colour graphics can help make a program easier to understand and to use. Not relying on screen size allows your program to move easily to new better screens and modes when they become available.
EASE OF USE. This is what window systems are about most of all.
All of the various elements described here are ultimately designed to
make the computer easier and more pleasant to use, over a wide range
of user experience and practice.
Easy to learn
Easy to re-learn
Easy to use productively
These things can conflict with each other, and with other things (e.g.
system cost, program size, program development time, backwards
compatibility). Design is not easy, and not all users agree.
Specific features of the Archimedes desktop environment:
Pop-up, context-sensitive, hierarchical menus. These provide rapid and convenient access to a wide selection of commands without continuously occupying screen space, and represent a considerable step forwards from the single-level, pull-down menus of other systems.
Control of multi-tasking and of memory. The Archimedes desktop envronment makes it easy to understand which applications are using memory, and how to get more. The memory-mapping hardware of the Archimedes means that issues about fragmentation of free space are overcome, compared to some other task-swapping systems. Desktop utility programs can be loaded and unloaded at will during the use of a large application, making small utilities considerably more useful than in other systems (where they often have to be loaded in at system startup, and cannot then be loaded or unloaded without resetting the machine).
Remember that the primary users of RISC OS are users and not programmers: consistent terminology, and the avoidance of jargon, are important in order to make RISC OS friendly. Because Archimedes is not totally a desktop machine some jargon inevitably slips through, but this should always be minimised.
Mouse terms:
press - press a button down
release - release a button
click - press and release
drag - press, move the mouse
double click - press, release, press, release
choose - what you do to a menu entry
type - what you do to keys on the keyboard
It is a common fault to confuse "press" and "click", and to talk about
"selecting" menu entries.
The model of files and filing systems presented within the RISC OS desktop is that files are always manipulated by their full path-name, including the name of the filing system, disc, etc. This gives each file in the system a unique name. There is no concept of "current directory". Every effort is made to ensure that people never have to type a full path-name, but they do have to see and (approximately) understand them.
Heavy use is made of the types of files. All files should be typed and datestamped, rather than being of the load/exec form from the old BBC world (but be prepared to meet these, and respond correctly).
Do not refer to, or rely on, the setting of the current directory.
NEVER build absolute drive numbers or absolute file names or absolute filing system names into your program. Check your program working from floppy, winchester, and econet, and ensure that installation is easy.
See below for rules about loading and saving files in programs.
Applications in the multi-tasking world are typically represented as a directory whose name begins with "!". The Filer provides various mechanisms to help such applications, so that the program and its resources can be treated as a single unit and installation etc. is easy.
Resources of any form can be held within an application directory. If an application is intended for international use then all textual messages within the program should be placed in a separate text file, so that they can be replaced with those of a different language. It may be unhelpful to read such messages one by one, however, as this forces the user of a floppy-based system to have the floppy containging the application permentantly in the disc drive. Error messages should all be read in when the application starts up, so that producing an error message does not cause an insert-floppy message to appear first.
Resources may also be written by the program during the course of execution. For instance, if an application has user-settable display options or state which should be preserved from one invocation of the program to another then saving it within the application directory means that the user does not have to worry about separate files containing such data. As a source of user-settable options this technique is preferable to reading an environment string, since with the latter system the user has to understand how to set up a boot file.
Some resources are of general interest to more than one program. Typical examples include fonts, and modules that provide general facilities. Such resources should be placed in the !System application, whose !Boot sequence sets a variable <System$Path>, or in a separate application such as !Fonts. It should be noted that the use of shared resources makes applications slightly harder to install, so check carefully that error messages are helpful if the shared resources cannot be located.
The rules above may break down for large applications. Some applications occupy more than one floppy disc, with swapping required during operation. It is difficult to give precise guidelines for such programs in general terms, because their requirements vary so widely. The rules above, however, will be used for many smaller programs and so will be reasonably familiar to users. Larger programs should be designed and organised to fit within the same general philosophy, so that users find them easy to install, understand and operate.
The key resource names that are built in to the system are as follows. The application directory is presumed to be called !Appl in the examples below.
!Appl.!Boot - this is the name of a file which is run when the application directory is first "seen" by the Filer. It is usually an Obey file (see documentation on the Obey module). Typical actions include:
(1) *IconSprites the !Appl.!Sprites resource file. This is done automatically if there is no !Boot file.
(2) Set a run-type for data files controlled by this application.
(2) Set a type name for data files controlled by this application.
The Filer only does this if the sprite !appl does not already exist in the Wimp sprite pool (sprite names are lower case). This prevents repeated delays from re-executing !Boot files (or even re-examining application directories). However, it relies on the various applications seen by the Filer having unique names, e.g. if you have more than one !System directory then only the first one "seen" will be used.
!Appl.!Sprites - this is the name of a sprite file. For an application directory !Appl this can provide a sprite !appl which should be used by the Filer, and also a sprite sm!appl for use in small-icon displays. It can also provide sprites that relate to data files controlled by this application, in small and large form (using sprite names file_xxx and small_xxx, with xxx being the hex identity of the file type). See below for rules about the appearance of sprites.
!Appl.!Run - this is the name of a file which is run when the application directory is double-clicked. It is usually an Obey file. Typical actions include:
(1) Execute !Boot - this will usually have been done already, but in the presence of multiple applications with the same name the !Boot file of a different one may have been seen first. Example: Run <Obey$Dir>.!Boot
(2) Call *Wimpslot to ensure that there is enough memory free to start the
application.
Example: *Wimpslot 150K 150K
Many applications know exactly how much memory they should be loaded with,
and manage to acquire more memory (often without the knowledge of the
language system underneath) by calling SWI Wimp_SlotSize. Paint/Draw/Edit
all maintain shifting heaps above the initial startup limit, ensuring that
extra memory is always given back to the central system when it is not needed.
Applications can also arrange to have the user control dynamically how
much memory they should have, by dragging the relevant bar in the Task Manager
display.
(3) If system resources are used then ensure that System$Path is defined, and produce a clean error message if it is not. Example: If "<System$Path>" = "" Then Error System resources cannot be found
(4) Ensure that any soft-loaded modules are present that the application
requires, using *RMEnsure.
Examples:
RMEnsure SharedCLibrary 0 RMLoad System:modules.CLib RMEnsure ColourTrans 0.10 RMLoad System:Modules.Colours RMEnsure ColourTrans 0.10 Error You need ColourTrans 0.10 or laterIf your call to RMEnsure can load a module from outside your application directory then you should call it twice, to ensure that the newly loaded module is indeed recent enough.
(5) Loading a module cannot steal memory from the "next" slot set up by wimpslot, so the memory set up by the *WimpSlot will still be valid - that is why *WimpSlot must be called before loading modules (e.g. in case all of free memory is in the next slot when the process starts). However, some applications wish to ensure that there is also some "free" memory after they have loaded, for example if they use the shifting heap strategy outlined in (2). Such applications may now at this point call *WimpSlot again, with a slightly smaller slot setting, to leave just the right amount in the next slot while at the same time ensuring that there is some memory free.
(6) Set an environment variable from <Obey$Dir> if you wish to access any other resources at run-time. This will give you the full path-name of your resource directory.
(7) Run <Obey$Dir>.!RunImage. This is the conventional name of the actual program. It is also used by the Filer to provide the datestamp of an application in full-info mode.
It should be emphasised that the presence of multiple applications with the same name should be thought of as an unusual case, but should not cause anything to crash. Also, complain cleanly if your resources can no longer be found after program startup.
There are, of course, variations on this startup sequence. It's quite common to bundle up existing applications so that they have an icon, and start neatly from the desktop environment. When doing this, note that it's possible to set the sizes of other memory areas in the machine using OS_ChanageDynamicArea. One point to note here is that the screen must not be allowed to grab memory from the "Next" slot - this can cause a crash. It is easily avoided by setting the next slot to 0 while setting up screen mode etc., e.g. see the startup sequence for !Lander which sets the next slot to 0 before setting the screen mode.
In a multi-tasking environment, memory should be used sparingly. Most simple applications require a fixed amount of memory, which can be arranged using a !Run file that specifies exactly the right *WimpSlot size.
Applications with more complex requirements can arrange to call Wimp_SlotSize at run-time to take (and give back) memory. Basic programs may use the new END= construct. C programs should call Wimp_SlotSize directly, the language run-time library (and malloc) will be entirely unaware that this is happening and so you must organise the extra memory yourself. A common way of doing this is to provide a shifting heap in which only large blocks of variable size data live. By performing shifting on this memory, pages can be given back to the Wimp when documents are unloaded.
DO NOT RECONFIGURE THE MACHINE. DO NOT KILL OFF MODULES IN ORDER TO GET MORE WORKSPACE. Such sequences are quite likely to be hardware-dependent and OS-version-dependent.
305 owners who wish to upgrade to RISC OS are warned that they should upgrade to 1MB machines first.
Programs should work in all screen modes in which the Wimp works. Read the current screen mode rather than setting it when your program is loaded, and read system variables to obtain resolution, aspect ratio etc. instead of building these into the program. Use Wimp_SetColour rather than GCOL (or ColourTrans, see below). At the very least, the program should not crash in inappropriate modes, but should display a message in your window, e.g. "256-colour mode only", as appropriate. Mode 0 is not usually useful, but worth making work if you possibly can, for users with big monochrome screens (mode 23). Also, try a square pixel mode (e.g. mode 9). Also check in modes 13, 15, 16, 18, 19, 20.
Think of an OS-unit as being a constant unit of measurement, rather than a fraction of the width of the screen (as was the model in the old BBC world). The standard assumption is that there are 180 OS-units to the inch, even though this may in fact vary between physical screens. "Device-independent" should be interpreted as meaning "the same absolute size in any mode" rather than "the same number of pixels" or "the same fraction of the screen".
Do not change the palette, but read and use the existing one.
Mode 16 is highly non-square, i.e. the aspect ratio is wrong. Do not try to correct for this automatically, it is an inevitable consequence of trying to fit a great deal of text onto a standard monitor.
There is a broadcast when the mode changes, so any mode-specific data can be changed at that point. Programs uninterested in colours must also check operation in 256-colour modes, e.g. some XOR-ing tricks do not work quite the same. For instance, the Wimp paints the caret (using XORing so that it can be easily unpainted again) with Wimp colour 11 (red) XOR'd with the colour code for Wimp colour 0 (white). This ensures that it always appears red when on a white background. The Clock application uses a similar trick for the second hand of the clock. As another example, Edit uses XORing with Wimp colour 7 to indicate its selection, but uses redraws in 256-colour modes.
In 2-colour modes the Wimp uses ECFs (dot patterns) for Wimp colours 1-6 (grey levels). Note that certain XOR-ing tricks do not work on these, and that use of Wimp_CopyBlock can cause alignment problems for the patterns.
Many programs choose to render graphics in "true" colours, and use the current palette to give as close an approximation as possible to the colour they intend. This approach to colour has the enormous benefit that it is not tuned to the limitations of today's hardware. The palette utility produces another broadcast when the user changes the palette settings, allowing such programs to repaint for the new palette. A soft-loaded module called ColourTrans is available (used by Paint and Draw) to give the closest setting possible to a given RGB value.
When should an application use true colours, and when should it use Wimp colours? As a general rule, any colours stored in documents and used when printing, should be true colours. Wimp colours are a convenient selection of contrasting colours for use when you don't really care what actual colours get used, as long as the result looks pleasant. True colours should be used whenever an object's colour really matters. The colours stored in Draw files, for instance, are true colours because the file has a precise meaning (of an image rendered on an abstract device) regardless of the current screen or palette settings.
The graphics printing facilities provided with RISC OS are based on the assumption that the same code should be used for redraw as for printing. There are various limitations in the printer drivers, all of which constitute good practice when writing to the screen too. Note that as a general rule, the use of the Draw module instead of Plot codes for line and area graphics means that a much better model of device-indpendent graphics is available.
A technique used on some systems is to remember the bitmap behind a menu or dialogue box when popping it up, to make removing it faster. This is not possible in a multi-tasking world because a window from a separate task may be changing in background. Rather than doing this, concentrate on making redraw FAST. One available technique for this is to use sprites to remember the contents of a window which are difficult to redraw quickly.
Another important technique for speeding redraw is the use of source-level clipping. During redraw and update, the Wimp always informs the application program of the current clipping rectangle. The redraw of icons, and of objects in Draw, is fast because this rectangle is used as a rapid test for the rejection of many redraw operations.
Do not use the system sprite pool in product programs, build a user one. The system sprite pool is present in Archimedes for backwards compatibility with the Master, and to help the construction of very simple programs.
Some program developers feel very strongly that a program should be able to take over the entire screen, without any scroll bars etc. It is perfectly possible for a program to do this and still benefit from the multi-tasking environment, as long as this is treated as a speicific mode of operation (chosen by a menu entry saying "Fill screen", for instance), and the program can also operate in a window. This facility can easily be implemented by opening a window the size of the screen, on top of all others. Some programs may even have special properties that only operate when in this mode, e.g. animation implemented using direct writing to the screen. The desire for this mode of operation, however, should not (alone) lead you to abandon the multi-tasking world entirely.
The mouse has three buttons, called SELECT (left), MENU (middle) and ADJUST (right).
When a "selection model" is being used for a set of objects, the
button actions should follows those of the Filer, Edit and Draw,
namely:
SELECT is used to make an initial selection
ADJUST is used to toggle elements in and out of this selection
(talk about "adjusting" the selection)
This is the origin of the names for the buttons.
Always use SELECT as the "primary" button of the mouse, used for pointing at things, dragging etc. ADJUST is used for less common or less obvious functions, or for slight variations and speedups. If you have no useful separate operation in any particular context, then make ADJUST do nothing rather than duplicating the functionality of SELECT: this is all part of training the user to use SELECT first.
Another technique for speedups and variations on mouse operations is to look at the setting of the shift key when the mouse event occurs. Such combinations should never be "necessary" to the operation of a program, e.g. a user experimenting with your program should not be expected to try all such combinations.
The Wimp detects double-clicks, typically used to mean "open object". It should be noted that a double click causes a single-click event to be sent to the program first. Some other systems avoid this, which may appear to simplify the task of programming but leads to reduced responsiveness to mouse operations.
Menus are accessed via the middle mouse button, referred to as MENU.
As a general rule an application should provide a single menu tree within a window, rather than a collection of little menus that require the user to point at a specific place in the window before pressing MENU. The problem with the latter approach is that it is hard for the user to determine the complete set of commands available.
(Aside: this is known as the "closure" principle. The user should be able to guess what your program can do, and discover fairly rapidly what it can't do, without having to search everywhere for hidden menus etc.)
It is reasonable for entries in the menu to be context-sensitive. In general such portions of the menu depend either on the object indicated when MENU is clicked (e.g. in the Paint file window), or on a "selected" object or objects (e.g. in Edit).
Standard colours for menus:
title is black(7) on grey(2)
body is black on white(0)
items 44 OS-units high
no separation between items
text is left-justified (except for keyboard equivalents, see "Keystrokes".)
The title says "Appl" (the application name) rather than "Appl Menu". Entries have initial letters capitalised and are in lower case otherwise.
Try not to make non-leaf menus too wide: reducing the horizontal travel necessary helps rapid selection in nested menus. Open the menu initially 64 OS-units to the left of the actual click, in order to aid this.
Do not grey out non-leaf menus. This helps the user to understand the complete set of operations available at any time.
Click on a non-leaf should have no effect (other than removing the menu tree) or should duplicate functionality that is available elsewhere.
Clicking SELECT or MENU on a menu entry should should choose the current menu item, closing the menu tree.
Clicking ADJUST on a menu entry should cause the relevant action to be performed, but the menu to remain. Flags, ticks, grey items etc. on the menu tree should reflect the new state after the action being performed. This is achieved in the following way. On a menu click, the application should call Wimp_GetPointerInfo and decide if ADJUST is being held down. If it is, re-open the same menu structure at the same location, and the Wimp will ensure that exactly the same positions are assumed by the various levels of the menu. This rule should only be broken if the object being referred to is destroyed by the action of the menu click.
(Note that you should call Wimp_GetPointerInfo BEFORE doing the operation chosen by the user from the menu, but the menu re-opening must be done AFTER the operation, so that any flags have been updated.)
Clicking outside the menu tree results in the menu being closed before the click event occurs. This allows the user to ignore the menu tree if no menu operation is required. To cancel the menu tree, the user clicks on the background. ESC also cancels the menu tree.
Menus produced from the icon bar should be moved up a little before opening, so that the relevant menu bar entry is still visible. The base of the menu should be 96 OS-Units from the bottom of the screen. The menu should be horizontally aligned so that the left hand edge of the menu is 64 OS-Units to the left of the point where the mouse click occurred.
Keyboard equivalents should be shown on the menu items for which they are short cuts. See the section named "Keystrokes".
The simplest way to provide dialogue boxes is as leaves of the menu tree. If the necessary windows are permanently created and linked to the menu data structure, then the Wimp will handle all opening and closing automatically. Alternatively, the menu tree can be so arranged that the application is informed when the dialogue box is being opened, this allows any computed data to be delayed until the last minute. For a large program with many dialogue boxes this is preferable, as the Wimp has a limit on the number of windows in existence between all tasks.
This form of dialogue box can be visited by the user without clicking on mouse buttons, just like traversing other parts of the menu tree. This is possible because redraw on Archimedes is typically much faster than on previous systems, so popping up the dialogue box and then removing it does not cause a significant delay.
Colours for dialogue boxes:
title is black (7) on grey (2)
title highlight colour is grey (2)
body is black (7) on grey (1)
writable fill-in fields are black (7) on white (0), with a border
action buttons are black (7) on cream (12), with a border.
Dialogue boxes match the colouring of menus, to show that they are "part of the menu tree".
Dialogue boxes do not have close boxes.
Provide a dialogue box that fully identifies the program, version etc. that is running. This is usually at the very top of the menu tree, e.g. the first leaf of the first branch. The leaf-name "Info" should be used to identify this within the menu tree, and the title "About this program" should be used for the dialogue box. See later remarks about program versions.
If a menu operation leading to a dialogue box has a keyboard shortcut, Wimp_CreateMenu should be used to initially open the dialogue box rather than Wimp_OpenWindow (athough Wimp_OpenWindow should still be used in response to Wimp_Poll (OpenWindowRequest). This will ensure that it has the same behaviour concerning cancellation of the operation etc. as when accessed through the menu tree.
There are various common forms of icon that occur within dialogue boxes, the most common forms are described here to improve consistency between applications.
Writable icons are used for various forms of textual fill-in field. They provide filter strings so that specific characters can be forbidden, alternatively arbitrary filtering code can be added to the application to ensure that only legal strings (within this particular context) are entered.
A writable icon should have a black border and a white background.
Code should be added to the handling of each dialogue box for the following
keystrokes. It's not possible for the Wimp to do this, because it doesn't
know the right ordering to use.
down-arrow: move to the next writable icon within the dialogue box,
or to the first if currently at the last.
up-arrow: move to the previous writable icon within the dialogue box,
or to the last if currently at the first.
RETURN: move to the next writable icon within the dialogue box, or perform
the default "GO" operation for this dialogue box if currently within the last
writable icon.
When moving to a new writable icon, the caret should be placed at the end of the existing content of the icon.
This term refers to "buttons" on which the user clicks in order to cause some event to occur, typically the event for which the parameters have just been entered in the dialogue box.
An action icon should have black (7) writing, a border, and cream (12) background.
The best icon to use is button type 7 ("menu"), with ESG not zero. This will cause the button to invert when the pointer is over it (like a menu item).
It is sometimes appropriate to provide keyboard equivalents for action buttons. For instance, if the dialogue box is available via a function key as well as on the menu (see "Keystrokes") then adding key equivalents for action icons may mean that the entire dialogue box can be driven from the keyboard. A conventional use of keys is:
RETURN in the last writable icon. Go, perform the obvious action initiated by filling in this dialogue box.
ESCAPE. Cancel the operation, remove the dialogue box. Note that ESCAPE is dealt with by the Wimp automatically in this case.
Function keys F1, F2, F3. If the action icons are arranged positionally at the top or bottom of the icon in a simple row, then define F1... as positional analogues of the action buttons, e.g. F1 activates the left-most one, F2 the next, etc.
This term refers to "switches", which can either be on or off.
The best icon to use is a text-and-two-sprites one. The text is left-justified and has the validation string "soptoff,opton" with the optoff and opton sprites within the default Wimp pool. This generates a box to the left of the text, with a star within it if the option is on (e.g. the icon is selected). The button type is 11.
This term refers to a set of options where exactly one out of a set of icons can be set.
The text-and-two-sprites form is again best, using the sprites "radiooff" and "radioon" from the default Wimp pool, and an ESG to force exclusive selection.
A static dialogue box is opened using Wimp_OpenWindow rather than Wimp_CreateMenu. A static dialogue box matches normal ones in colours, but has a close box.
One common form of use is a "tool" dialogue box. This typically consists entirely of action icons, and is used in preference to a submenu because the typical mode of use is of rapid switching between the tool box and the pointer. An example is the colour and tool windows in Paint. These are activated (for a given sprite) using menu entires "Show colours" and "Show tools".
Another reason to use a static dialogue box is that it may be appropriate to attach menus to a dialogue box.
Another reason is that it's not possible to drag an icon into a normal dialogue box from another application, because as soon as the drag starts the menu tree is cancelled (see the sections on loading and saving files).
When you gain the caret, do not automatically pop above other windows in the stack. Also, a window should generally only gain the caret if the user clicks inside it - the exceptions being menus and dialogue boxes, which should give the caret back to the previous owner when they close - this is done automatically by the Wimp for menus and non-static dialogue boxes.
If you receive a keystroke that you do not understand or use, hand it back to the Wimp using Wimp_ProcessKey. This allows other windows to provide hot-key operations that work anywhere, it also allows the Wimp to do function key expansion in the last resort.
Keyboard speedups for menu operations are useful to expert users. Reminders of their existence should be placed right-justified in the relevant menu entry, as in the following examples:
(ctl-X) control character (f3) function key (shf-f3) shifted function key (ctl-f3) control function key (ctl-shf-f3) control shifted function key (ctl-alt-shf-f3) most complex example: control, alt and shift
Use function keys for most speedups. use ^Z, ^X, ^C and ^V for operations that refer to a "selected" object or objects:
ctl-Z clear selection ctl-X delete selection ctl-C copy selection ctl-V move selection
This allows the expert right-handed user to access these operations extremely rapidly.
Use ALT as a shifting key rather than as a function key. Different forms of international keyboards have standardised the use of ALT for the entering of accented characters.
Do not forbid the use of top-bit-set characters in your program, as many standard accented characters are available there. These characters are clearly distinguished from the function keys by the Wimp.
Due to their frequent polling of the Wimp, window'd programs do not normally need to use escape conditions. The Wimp sets the escape key to generate an ESC character. If you perform a long calculation without calling Wimp_Poll, you may set the escape action of the machine to set escape conditions (using *FX 229,0), as long as you set it back again (using *FX 229,1 and then *FX 124) before calling Wimp_Poll.
Significant applications typically have an Info box of a standard format, that gives the version number of the application being used. Provide it at the top of the menu in the icon for your program. Copy closely the form of dialogue box used in the Welcome Suite applications.
Very small applications need not have this, but all programs should also be identifiable by a version number on the first line of their !Run file.
An editor is a program that presents files of a particular format as abstract objects which the user can load, edit, save, and print. Text editors, word processors, spreadsheets, draw programs are all editors in this context. Their data files are referred to as documents.
Each document being edited is typically displayed in a window. Such windows are referred to as "editor windows".
Most editors, for each document currently being edited, record whether the user has made any adjustments yet to the document. This is known as an "modified flag".
The title of an editor window is conventionally the filename of the current document, centred, with a postfix " *" if modified. The minimum size can be set to ensure that this does not restrict the window's minimum size. Use "<untitled>" if the document has not yet been saved or loaded. If there are multiple views of the same document then postfix " %n" to this, where %n is the number of views of this document that exist.
Standard editor window colours:
title fore is black (7)
title back is 2
title hilight is 12 (input focus indication)scroll outer is 3
Some editors are capable of editing several documents of the same type concurrently, while others can edit only one object at a time. Being able to edit several documents is frequently useful, and removes the requirement for multiple copies of the program to be loaded. Such programs are referred to here as multi-document editors. Edit, Draw and Paint are all multi-document editors, while MusicEd and FormEd are not.
Editors use RISC OS file types to distinguish which application belongs to which file. Their !Boot files should give a name, a sprite (in the Wimp sprite pool) and a run action to such file types. File types are allocated by Acorn ISV support.
The user interface of RISC OS concerning loading and saving documents is rather different from other systems, because of the permanent availability of the Filer windows. This means that there is no need for a separate "mini-Filer" which presents access to the filing system in a cut-down way. Although this may feel unusual at first to experienced users of other systems, it soon becomes natural and helps the feeling that applications are working together within the machine, rather than as separate entities.
Icons on the icon bar represent facilities and services available within the computer that are offered by currently running applications. Some of these directly represent hardware devices or filing system access points, these go on the left of the icon bar. The rest are purely software services, and go on the right. Each application is typically represented by just one icon.
When an editor is loaded it registers an icon on the icon bar. This icon is typically the same as the one used to represent the application within the Filer.
An editor typically needs two (related) icons: one for data files, one for the application. The latter is used for the application in the Filer. Clicking this usually creates a blank data object, or opens the current one if your program can only edit one at a time.
Normal size for file icons, and for things on the icon bar:
68 OS-units high
68 OS-units wide
Icons with a different height are strongly discouraged, as they will have
their top edges aligned within the filer "large icon" display. A wider icon
is permissable, but the size above should be thought of as "standard". If
the width is greater than 160 OS-units then the edges will not be displayed
in the filer "large icon" display.
Icons are often displayed half size to save screen space. Hand-tuned small versions of icons are usually provided.
Check the appearance of icons in 2, 4, 16 and 256 colour screen modes. Do not assume that your customers have a MultiSync monitor. Note that icons must not be defined in 256-colour modes (the Wimp can't cope).
Icons for files conventionally have a black border 4 OS-units wide. Icons for devices conventionally have a grey (5) outline and cream (12) body. Icons for applications are conventionally not square (thus requiring a mask) and related in some way to the documents files that they edit.
The standard ways of starting an editor are:
Either:
Double-click on the application icon within the Filer
Or:
Double-click on a document icon within the Filer
The action taken in the first case is to load a new copy of the application. The only visible effect to the user is that the application icon appears on the icon bar.
The action in the second case is to load a new copy of the application, to register its icon on the icon bar, to load the specified document and to open a window onto the document. This effect typically occurs by the activation of the run-type of the document file, which in turn will invoke the application by name with the pathname of the document file as its single argument.
Newly opened windows on documents should be horizontally centred in a mode-12 screen, and not occupying the entire screen. This emphasises that the application does not replace the existing desktop world, but is merely added to it. Subsequent windows should not totally obscure ones that this application has already opened, e.g. use a small offset with each new window.
The action in the second case is modified if a multi-object editor of the correct type is already loaded. In this case, the existing application will notice the broadcast from the Filer that a double-click has occured, and will open a window on the document itself. For details, see the Data Transfer Protocol documentation.
A further way of opening an existing document is to drag its icon from the Filer onto the icon representing the editor. In this case, a data load message is sent by the Filer to the editor, which can edit the file. This form is important because it specifies the intended editor precisely, for instance if both Paint and FormEd are being used (both can edit sprite files) then double-clicking on a sprite file could load into either.
In a multi-document editor, clicking on the editor icon on the icon bar creates a new, blank document in a newly opened window. If arguments are required in creating a new document, it may also be appropriate to use a dialogue box during the course of this process. If a style sheet is required (e.g. for a DTP program) then it may be appropriate to use a static dialogue box, and drag the style sheet from the Filer.
The window created from the loading or creation of a document should be no larger than the windows created by Edit, and should be in the same position on the screen. Stagger further new windows down by 48 OS-units for each new window, but if this would overlap the icon bar then return to the original starting size and position. The initial size and position of windows should be user-configurable, by setting a window in a template file.
In a single-document editor, clicking on the editor icon on the icon bar creates a new, blank document if there is not already a document loaded. If there is already a document loaded, this moves the document window to the front of the window stack, in case it has been obscured by other windows.
To open an existing document, double-click on the document in the Filer. This will cause a broadcast from the Filer when it's about to open something, so if your editor can edit multiple documents it can catch this broadcast and load the document into the existing editor.
To insert one document into another, drag the icon for the file to be inserted into the open window of the target document. The Filer will then send a message to that window, giving the type and name of the file dragged. The target (if the file is of a type that can be inserted) can now read the file. If the file is not of a type that can be inserted in this document then the editor should do nothing, e.g. no error message is produced.
To save a document, provide a dialogue box as follows.
| |
| Save as: | | |
| || --------------------- ------ |
| - - - - - - - | | | | | | | | | | | sprite | | | | | | | | | - - - - - - - | | |
| | <writable> | | OK | || --------------------- ------ |
The dialog box consists of a sprite icon, a writable icon, and an action icon. The exact dimensions should be copied from the palette utility. The writable icon should have the caret at the end. More options may be added if necessary, as appropriate to the document type in question.
This is the standard equivalent of the "minifinder" in other systems. If there is no file name then invent a simple leaf name, e.g. TextFile in Edit, so that just dragging will not cause an error.
The user can now:
(1) hit RETURN or click on OK to save in the already named file (clicking on the menu entry that leads to this dialogue box
should have the same effect)(2) edit the filename as desired using the keyboard (3) drag the icon into a directory viewer (4) hit ESCAPE to cancel the operation.
(1) is used when saving an already saved document. (3) is used when specifying a destination directory for the save. (2) is used when editing the leaf-name of the file. Typically, it is necessary to do (2) and (3) when first saving a file, and (1) thereafter.
When (1) happens, the application should check that the proposed name does at least contain one '.' character. This prevents a common error in beginners, who just see the proposed leaf name, and attempt to press OK immediately. The error message "To save, drag the file icon to a directory viewer" should be used for this case.
When a drag happens, send a message to the window where the drag ends, saying that you want to save the file. The window (if it is a dir viewer) will reply with the name of the directory. Append your leaf-name to this and save there.
If the save is succesful, update your stored name for the document and remove the dbox: the operation is complete. Check return codes and errors from saves.
"Save" should be interpreted as being like "save and resume" from some other systems, e.g. after the operation the user is still editing the same document. Save should cause the document to be marked unmodified, unless the save was to a scrap file (see the section on data transfer).
Remember the datestamp on a loaded document. If the document is stored without being modified, save with an unchanged datestamp. Otherwise, save with the current datestamp and update the retained datestamp for the document.
Saving a portion of a document (e.g. "Save Selection") may be grouped either with other save operations, or with the Save File operation. If there are several possible selection save formats then putting it on Save may be more appropriate. Balancing submenus may also be an issue. Edit and Paint, for instance, group it with other selection operations while Draw (which has several different forms of Save Selection, and many other operations on the Selection submenu) groups it with Save File.
If the user clicks on the Close icon of a document window,
and there is unsaved data, then you should pop up a dialogue box
asking:
Do you want to save your edited file? (if the document has no title)
or:
Do you want to save edited file '%s'?
You can copy this dialogue box from Edit's template file. If the answer
is Yes then pop up a save dialogue box, and if the result is saved then
close the window. If the answer is No, or any cancel-menu (e.g. ESC)
occurs, then the operation is abandoned.
An additional feature that can be implemented on the close button is as
follows: if the user clicks ADJUST on the close icon then close the
document, and open the parent directory viewer (using *filer_opendir). This
is similar to the use of ADJUST on the close icon of a directory viewer: the
directory tree, and the documents within it, are thought of as a continuous
tree of information over which the user navigates. If he clicks ADJUST with
shift held down, or with the document modified, just open the parent.
A Quit operation should be supplied at the bottom of the menu attatched
to the icon of an editor. If it is selected when there is unsaved data,
then ask the question:
%n file%s edited but not saved in <prog>: are you sure you want to Quit?
(The %s should be "s" if the %n is not 1, else "".)
The same question should be asked if a desktop-closedown sequence occurs. In such a case, if the answer is Yes, then the desktop-closedown sequence should be restarted by sending a shift-control-f12 keystroke message to the original sender of the desktop-closedown message.
One of the most powerful aspects of multi-tasking in RISC OS is the direct dragging of data from one application to another, and its easy import and export in a variety of formats from applications.
Think of a data format as a commitment to forwards and (if possible) backwards
compatibility. Write an extremely careful definition of your data format, and
try to build in:
testing for the correctness of the file
version control for the file format
extensibility for the file format
If your application is successful and widely used then other software
authors will be tempted to write other programs that perform other
operations on the data formats that you have defined. Work hard to encourage
this! Send a copy of such a format definition to Acorn ISV support, it will
then be available to other ISVs as an embryonic de facto standard for that
particular type of data.
Do not reinvent the wheel. If there is already a data format out there to describe what you want then use that: even if it comes from a computing system or background that you do not intend to work with.
Do not take idle events unless you have to. They slow everything down. If you do need to take null events, Wimp_PollIdle is preferable to Wimp_Poll, unless the user is directly involved (eg. dragging an object) and responsiveness is important.
If you set your own pointer shapes, use pointer 2 for them. Set back to pointer 1 (the standard generic arrow) on a pointer-leaving-window event. Pointers 3 and 4 are used by the hourglass.
Do not use mouse colour 2, as it behaves strangely on hi-res mono screens (e.g. it alternates between black and transparent!).
Do not pop your window to the front when grabbing the caret, and do not grab the caret when your window is popped to the front. You should only grab the caret as a response to clicks within your work area.
The Wimp's drag operations are specifically for drags that must occur outside all windows. As well as the crawling-box form they allow the use of user-defined graphics, allowing arbitrary objects to be dragged between windows.
If you build drag operations within your window, check that redraw works correctly when things move in background (the Madness application is useful for this). Also, it is important to note that such "within-window" dragging must use Wimp_UpdateWindow to update the window, rather than drawing directly on the screen.
If the drag works with the mouse button up then menu selection and scrolling can happen during the drag, which is often useful. Stop following the drag on a pointer-leaving-window event, and start again on a pointer-entering-window event.
If the drag works with button-down, then it may continue to work if the pointer is moved out of the window with the button still down. Alternatively for button-down drags, you can restrict the pointer to the visible work area, and automatically scroll the window if the pointer gets close to the edge.
Always check all error returns from Wimp calls. This includes Wimp_Poll, which can fail in rare circumstances.
Beware errors in redraw code, they are a common way for systems to lock up (because the redraw fails, the Wimp asks you again to redraw, and so on). A suddenly missing font, for instance, should not lead to infinite looping. Check that the failure of window or icon creation does not lead you to crash or lose data. Check cases concerning running out of space.
Do not use Wimp_CopyBlock during redraw, even if you know that the source is
visible: Wimp_CopyBlock should be used outside the redraw loop, to copy
whatever relevant areas of the window are visible, and cause
redraw-window-events for the rest. Redraw routines should be very similar
(or identical) to routines used to print graphics, for which CopyBlock (and
XOR-ing tricks) will not work.
If the user is asked to insert a floppy disc and hits "Cancel", you get an error "Disc not present" or "Disc not known" from ADFS (look up the IDs in the PRM). If you get either of these errors from an operation you need not call Wimp_ReportError, just cancel the operation. This avoids the user getting two error boxes in a row.
There are two clocks showing real time in the system, the hardware clock and a centisecond timer. The two can diverge by a few seconds a day, but are resynchronised at machine reset. For consistency, always use the centisecond timer.
Do not have phrases like "at line 1230" in error messages from Basic programs. "(internal error code 1230)" is preferable.
DO NOT BYPASS OS DEVICE INTERFACES AND ACCESS HARDWARE DEVICES DIRECTLY! DO NOT PEEK AND POKE PAGE ZERO LOCATIONS, OR KERNEL WORKSPACE! Such tricks may well NOT WORK on future machine and operating system upgrades. Acorn will pursue a policy of continuous improvement and expansion for its Archimedes product-line: build your software to last.
The File dialogue box provides useful information about a file being edited. Provide it at the top of the menu in a file window, or within a Misc submenu there (if there are other miscellaneous menu entries to collect).
Filenames of up to 255 characters should work. Longer filenames should not crash your application.
When using Wimp_PollIdle, remember that monotonic times can go negative
(e.g. wrap round in a 32-bit representation) after around six weeks.
So when comparing two times,
(newtime - oldtime) > 100
is a better comparison than
newtime > oldtime + 100.
This problem caused early versions of MailMan to go wrong after six weeks of
continuous use.
Interactive help is extremely easy to provide via the !Help application: doing so enormously increases user's confidence that all desktop applications are working together. It may even be helpful too, particularly to occasional users of the package who just need a little reminder of what it does.