This page contains a somewhat random collection of hints about writing ROX applications. Some of them are general, some are specific to ROX. Of course, you don't have to follow these; they're just guides. But you should have a good reason before deviating from them.
Since ROX is very much about a particular user interface style, ROX applications don't follow all the normal rules.
But we do follow most of them, and they're worth knowing anyway so you know when you're breaking them on purpose,
and when you're just being stupid ;-)
For consistancy, the ROX documentation tries to use the following words with the meanings given here:
ROX applications should be distributed as application directories. An application directory contains all the resources that a program needs (source code, binary, images, help, etc) in a form that can be used directly without the need for any installation.
They must be relocatable at run-time, so don't put any absolute paths into your programs (ie, don't assume the application lives in /usr/local/apps, etc). Don't assume the user installing the software has root access.
ROX applications should not normally be supplied with any kind of installer. This makes software installation simpler and easier for everyone, and completely automatic for Zero Install users.
There are a few cases where you might want to install shared resources. Some of these are examined here:
As you can see, all these rules mean that you should never have to preform any actions at install time.
A ROX application is started by clicking on its application directory, which runs the file AppRun inside. Users will not normally be able to pass flags to your program (although they can give arguments by dragging files onto it).
When run, your program should give the user visual feedback that it is loading. Try to open the main window as soon as possible, even if it appears blank at first. This allows the user to move their eyes to the area where the content is going to appear. It also means they can reposition the window while the program is loading to get it where they want it.
Splash screens may be placed inside the main window -- do not use separate windows or set override-redirect because the user may want to continue working while the program loads.
A better solution than a splash screen is to simply load quickly in the first place! If your program takes a long time to load, see if you can defer some of the initialisation until later.
For example, ROX-Filer only builds the Options window when it is opened, not when the filer is loaded, and it will open a directory viewer before it has finished scanning the directory.
ROX uses drag-and-drop for file operations. Users load files by dragging to your application directory. They import files by dragging into a document window. They save by dragging back to a filer window. See Edit for an example of this.
The traditional method of using a 'mini-filer' window is bad because:
When some data (not in a file) is dropped onto your application directory, ROX-Filer will ask you to load '-' and passes the data in on standard input. Make sure you support this!
Menu items names:
See also:
Do not over-use dialog boxes. If a dialog box pops up, then it should usually be worth the user's while to read it.
Confirmation boxes that appear too frequently are useless; the confirming click becomes part of the action and the net effect is simply slowing the user down without gaining any safety. Whereever possible, operations should be undoable. This allows a fast interface without any confirmations, but also protects the user from all mistakes. Generally, therefore, it is only worth confirming an operation which would take a reasonable amount of work to recover from.
Do not use button labels like Yes and OK if there is more than one button. Instead, use a verb (such as Delete or Send). If the user knows what their options are (eg, whether the data is to be saved) then they should be able to work out which button to click without reading the text. This also prevents mistaking one dialog for another, eg:
Using image icons in the buttons can also help here.
The GNOME developers have decided on some guidelines for button ordering which seem pretty sensible. The basic idea is that the 'Yes, do it' button goes in the bottom right corner. This is not necessarily the safest choice. We have moved across to this system too.
Note: we're not following all of GNOME's advice on dialog boxes, so don't do anything stupid like this (note the two negatives!)...
Instead, just open the normal save box, but with an extra 'Discard' button. The user already knows how the save box works, so there shouldn't be any confusion.
When reporting errors, always say why the error occured. Sometimes it's difficult to know the root cause of a problem, but you must have had some reason to have shown the box in the first place... tell the user whatever you know. Don't do this:
If you are using ROX-Lib, uncaught exceptions will be automatically displayed in a box like this:
You can catch specific errors and make them more user-friendly (the above screenshot, created by saving from Edit to root's home directory, isn't ideal). In general, I prefer to err on the side of providing too much information than too little (which path was read-only may be obvious in some cases, but completely non-obvious in others). I'd rather a user sees the stack-trace box with full details when they don't need it, than not get the information when they do.
The ROX-Lib error dialog also has a Details button which provides access to the stack trace, local variables and an interactive Python prompt for more advanced users. This is open source; encourage users to explore!
Never catch all errors and just assume what the problem was. MS Word does something like this:
try: doc.save() except Exception: alert('Disk full. Try deleting some files.')
Users can delete a lot of important files before someone less trusting of error messages helps them out ;-)
Screen space is precious. Don't waste it with clutter! You either reduce the area available for showing the user's data, or you cover other programs. Programs should use drag-and-drop to work together and small windows make this easier.
In general, you should start off with the most minimal interface possible (ie, just showing the data). Add extra user interface features only if they are needed. Do NOT start a new application by creating toolbars filled with non-functional buttons all around your window!
Toolbars:
Toolbars are generally OK if they're small. Don't put too many tools on the bar though -- searching for the tool you want may waste more time than just using the popup menu. Users are more likely to investigate five tools than thirty.
Menu-bar:
Try to avoid these. A menu bar is slower to access than a popup menu, and wastes screen space. Only use one if you have a very large main window and lots of menus.
The preferred method for giving commands in ROX applications is the popup menu. Popups have the following advantages over other means:
- They appear instantly, right under the cursor. No time wasted moving the mouse.
- They are arranged in a hierarchical structure. All the functions of the program are shown in one place.
- GTK+ makes it very easy to bind keys to menu items (by pressing the key while pointing at it).
- Popups don't waste any screen space when not in use.
All toolbar functions should also appear on the menu so that keys may be bound to them.
Status-bar, Preview panes, etc:
These are usually a bad idea, but it depends on the application. Put them in if they become necessary.
A wizard takes the user through an operation step-by-step, because the operation is too difficult for the user to perform on their own. The need for a wizard usually indicates a problem with your user interface. It is often better to fix the problem than to write the wizard.
For example, consider the task of making a chart in a spreadsheet when the user clicks on the 'Chart' tool:
A wizard-based approach would bring up a long series of dialog boxes asking the user for the chart type (bar/line/pie/scatter), title, axis labels, grid lines and so on.
A non-wizard approach would display a chart with suitable defaults immediately and let the user change anything that was wrong using the normal editing tools.
The second approach has a number of advantages:
It's often better to tell the user how to do something than to do it for them. A good example is setting the program to handle a particular type of file when no default has been set. ROX-Filer tells the user to use the `Set Run Action...' menu item; they'll know how to change it again later. Explorer brings up a dialog for them; most Windows users have no idea how to change a file's run action a second time!
If you want to add scripting facilities to your program, make sure you use an existing language. Python, PERL and scheme are all easy to embed in your applications and are sure to be faster, more powerful and less buggy than any language you write. There's also a good chance that users will already know the language.
Look into this early. It starts with a #include in the app's config files and before you know it you've been suckered into adding support for lambda expressions, nested modules and garbage collection!
Which language you choose is up to you, and depends on the application. However, many ROX applications are written in python and this is surely the best language for beginners (and possibly experts too ;-).
In fact, it's often a good idea to write the whole application in a high level language as you avoid the whole problem of compiling (many users don't have a compiler, don't have the header files, run on multiple architectures, have wierd compilers, etc). Usually only very small parts of your program will benefit from being written in C; most languages allow you to embed small C functions easily.