Style Guide

Introduction

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.

Futher reading

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 ;-)

Terminology

For consistancy, the ROX documentation tries to use the following words with the meanings given here:

Select
Cause something to become selected, such as an icon or a piece of text.
Choose
Choose an item from a menu.

Software installation and startup

Installation

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:

Icons for filetypes
It is the user's choice what icon to use to represent each type of file. You should only set the icon for a file type if there isn't one set up already, and this should be done when the program is run, not when it is installed.
When your program is run, if <Choices>/MIME-icons/type.png is missing (or a broken symlink) then you may symlink it to an icon inside your application.
Note that we support freedesktop.org's icon theme spec in the CVS version of the filer. In that case, install your icon as mime-application:foo into the default theme (hicolor). This will make it visible to other desktops, too (support for this may take a while to catch up).
Packagers for distributions may choose to set a system-wide icon when the package is installed; this must be coordinated over the whole distribution to avoid conflicts.
MIME-info rules (guessing a file's MIME type from its name)
Like icons, MIME-info rules should be installed at run-time. Drop an XML file with your program's name into the shared MIME package directory (see freedesktop.org) and
run update-mime-database.
MIME-types (what application handles each type of file)
ROX-Filer provides a very easy way for users to specify which application should handle a particular type of file. Do not set this yourself.
Services
Programs which should be run automatically on startup should also not set themselves up at install time. You may ask the user if it's OK to be run automatically when they run the program. This allows users to install software without worrying about opening security holes.

As you can see, all these rules mean that you should never have to preform any actions at install time.

Start-up

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.

Loading and saving

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:

  • The user must learn two interfaces (the application and the filer) which do the same thing -- navigate the filesystem.
  • Mini-filers either have too little functionality (eg, can't create a new directory, can't search for files) or have too much and are confusing.
  • It should be the user's choice which filer to use for all applications, not the application author's choice on a per-application basis.
  • Mini-filers invariably default to the wrong directory. In ROX, the user can have multiple filer windows open, drag to pinboard and panels and so on.
  • Drag-and-drop saving allows the user to save directly from one application into another.

http://rox.sourceforge.net/screens/saving.png

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:

  • Save As... opens a savebox. Most programs only need to provide this. It is called Save As rather than Save to avoid confusion with Window's Save behaviour.
  • Quick Save saves directly using the current filename without opening a savebox. This is what many systems call Save, but to avoid confusing with
    RISC OS we use a different name.

See also:

Dialog boxes

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:

  • Do you want to save? : Yes
  • Really quit without saving? : Yes

Using image icons in the buttons can also help here.

Buttons

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.

http://rox.sourceforge.net/screens/dialog.png

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!)...

http://rox.sourceforge.net/screens/save_alert.png

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.

http://rox.sourceforge.net/screens/save_discard.png

Errors

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:

GNOME error box

If you are using ROX-Lib, uncaught exceptions will be automatically displayed in a box like this:

ROX-Lib error box

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 ;-)

Toolbars, menubars, etc

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.

Wizards

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 usually faster, because the user only changes things the program got wrong.
  • If the user is trying to make a sketch graph quickly, they don't have to mess around with things like the grid type which they don't care about.
  • The user feels comfortable making changes to the graph later. A wizard-user will often have to delete the chart and start again every time they wish to change something.

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!

Scripting

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.

Applets

  • Please make sure the menu appears in the right place (the same distance from the edge of the screen as for other items on the panel).
    See ROX-Lib's applet class for an example implementation.
  • Make sure that your applet can expand and shrink as the panel size changes (use Options -> Panels -> Panel width to change it).