MetaCard Corporation

Part 5: Sample Application (font chooser)

Application Design

In this section we describe the implementation of a simple, yet useful, application in each of the environments. Considerable effort has been made to avoid choosing an application that overly favored one environment over another. This is especially difficult in the case of MetaCard, since the IDT makes construction of layout-intensive applications much easier. MetaCard also has a database built-in in the form of the multiple card architecture, so applications such as calendars, note-pads and address books are trivial to develop. These types of applications would be much more time consuming to produce in the other environments.

Due to development time restrictions, large scale applications and those that require extensive C coding could not be considered. Since this is the strong point of Tcl/Tk, the sample application doesn't demonstrate one of the best aspects of this tool.

Since dtksh lacks support for color bitmap and object graphics, and since the Xt/Motif text widget lacks support for many of the formatting and hypermedia features present in MetaCard and Tcl/Tk, we had to rule out all applications that require graphical displays of data and interactive multimedia presentations.

One sample application that meets all of these restrictions is a font chooser dialog, similar to that found in a word processing application such as Microsoft Word. The dialog allows the user to select a font, a point size, and a style. A preview area shows the font defined so far. When the OK button is pressed, the X Logical Font Description (XLFD) name used to load the font is output to the dialog's standard output. The MetaCard version of this dialog is shown in Figure 1. The applications developed in the other two tools look very similar and so aren't shown.

Screen Shot

Figure 1: MetaCard Version of the Font Chooser Dialog

The scripts used for the different implementations of the font chooser dialog are shown in the Font Chooser Example Scripts: Tcl/Tk, dtksh, and MetaTalk.

A similar comparison of a directory browser application written Tcl/Tk with the same application development in MetaCard is available as MetaCard and Tcl Directory Browers

With all three tools, the first step in building an application is to construct the user interface. In most cases, several different possible layouts of the controls are tried and the one with the best look and usability is selected. Next, scripts are added to handle each of the controls. This is also a dynamic process, where short sections of the scripts are written and then tested immediately. Finally the interactions between the controls are tested to ensure that they function properly.

User-Interface Components

All three tools support the full range of user interface components: push buttons, radio buttons and check boxes, labels, editable text fields, list boxes, menus and dialog boxes.

Tk has a wide range of special-purpose controls and has a simple and consistent naming scheme for resources and callbacks. Tk lacks built-in support for option menus, and lacks a "default" style for buttons (the double border around the button that is activated when the user presses the return key). Keyboard traversal to buttons and scrollbars also isn't supported in the current version, though this is scheduled be added to the future Motif-compliant release of Tk.

dtksh supports the widest range of controls and of optional behaviors for the controls of the three tools. Although this makes it the most flexible tool, it also makes it the most difficult to master. The problem is exacerbated by the common use of different terms for similar features in Xt/Motif. For example, the text in a label (non-editable) widget is called the labelString, while the text in an editable text widget is called the value. The callback for selecting a push button is called the activateCallback, while for toggle buttons it's called the valueChanged callback.

Rather than the wide range of widgets available in the Motif toolkit, MetaCard is built on a few control types, each of which can be configured to look and behave in a wide range of ways. For example, the button control can be a push button, a check box or radio button, or a menu button depending on how its properties are set. The field control can be either editable or non-editable, or even a list box. Like Tk, MetaCard supports object graphics as a control type, which makes developing applications that require odd-shaped buttons easier than with the other tools.

Layout

The starting point for building the font chooser application in MetaCard is to lay out the dialog using the IDT. Controls are constructed by choosing the appropriate tool and dragging out the size and shape required. Double clicking on an object brings up a properties dialog that allows you to set the name and other attributes of the object. Alignment of the controls is done by selecting multiple controls and using one of the resizing/alignment routines available in the layout dialog box.

In contrast, layout of the same dialog in dtksh or Tcl/Tk is a much more tedious process. Each time you make a modification, the dialog must be destroyed and the script that constructs it edited and rerun. Since you can't tell what the interface will look like from examining the script that creates it, it often takes several tries to get a control positioned and sized correctly. The vendors of IDTs for the Xt/Motif toolkit claim improvements in productivity from 2 to 10 times over doing layout without an IDT. Since development of the user interface typically takes from 25 to 50% of the total time required to develop an application, high productivity in this area is an important advantage.

A related concern is the ultimate quality of the interface produced. With an IDT, it is easier for the developer to take the time to make sure that the interface is logically laid out and aesthetically pleasing. Without one, the layout process is often terminated as soon as the minimum functionality is achieved because it is too time consuming to tweak the interface in an effort to optimize ease-of-use or aesthetics.

Even without the need to try different arrangements of controls, which I had already done in MetaCard, layout of the font chooser dialog with the other two environments took experienced developers at least 4 times longer than the layout time in MetaCard.

Geometry Management

Both dtksh and Tcl/Tk have manager widgets that resize and reposition their children when they are resized. The layout rules are specified as attachments and constraints. For example, a button might be attached to the left edge of the manager, and set to be 20% of the width of the manager. The advantage of this approach is that the layout and resize process is automatic; the developer does not need to write any code to manage the process.

The major drawback to this approach is that in many cases it is difficult or even impossible to specify the constraints properly. Those this is also a problem with the Tcl/Tk geometry managers, it is more serious with the Xt/Motif-based dtksh:

The creation of a visually appealing and usable Motif user interface will often require an application designer to lay out control widgets in a way that is not easily achieved using the standard Motif manager widgets.

In such cases the ideal solution should be to implement a custom widget that provides the appropriate control layout. Unfortunately, the complexity of writing such a widget often outweighs the benefits from doing so, and the developer will end up trying to trick the existing Motif widgets into giving an acceptable layout.

-- Alastair Gourlay, "The One-Minute Manager" X Resource, Issue 10, p 63.

Using manager widgets to enforce a desired resize behavior is not easy for new Motif programmers. Actually, it's not very easy for experienced Motif programmers either.

-- J. Stephan Pendergrast, Jr., "Desktop KornShell Graphical Programming", p 170.

Dialogs that degenerate into useless (and ugly) configurations are all too common in Xt/Motif applications. The constraint managers used in this architecture can also override the user's preferences. For example, the Xt/Motif file selection dialog has the annoying habit of resizing itself to a fixed size every time a directory is changed, despite a user's best efforts to keep it large so that more files can be seen at one time.

Since most dialogs don't need to be resizable, many application developers just spare themselves the trouble of fighting with the geometry management issues and make the dialogs non-resizable. This not much of a sacrifice: resizable dialog boxes are extremely rare in Macintosh and Microsoft Windows applications. Another example is that most of the dialogs used in HP's Vue desktop environment (the basis of the COSE desktop) aren't resizable..

MetaCard lacks a constraint-based geometry management system. Instead, the developer must write a script to resize and reposition the controls when the resizeStack message is sent. Like the scripts used to construct the interfaces in dtksh and Tcl/Tk, these resize scripts can be tedious to write since every control must be specified separately. However, unlike the with constraint-based geometry managers, with this algorithmic method it is always straightforward to get the look you want.

Dialogs such as menus are very easy to build with constraint-based geometry managers since all of the buttons are the same size, and are arranged such that they are touching each other. The font chooser dialog, on the other hand, was particularly difficult to lay out with geometry managers since it is very irregular. Since the dialog was initially laid out so that everything could be seen, it was not necessary to make this dialog resizable. In order to ensure that the interfaces looked the same for all three applications and to reduce the length of the dtksh and Tcl/Tk scripts (since manager widgets did not need to be created and offsets and attachments specified), a short MetaCard script was used to dump out the coordinates of the controls I had laid out in a form usable by dtksh. A similar script was used for layout of the Tcl/Tk version of the application

Resources/Options/Properties

In dtksh, as with most applications based on Xt/Motif, resources are used to specify things like the fonts and colors used in an application. With Tk the term "option" is used instead of the term resource. In both of these environments, resources can be set either directly in the scripting language or through the use of the X resource system (e.g, with the .Xdefaults file).

Unfortunately, X resource files can be very confusing to non-programmers. It is very easy to accidentally alter a resource file such that an application looks bad and is difficult or impossible to use. For this reason, most commercial applications allow only limited (if any) access to this method of changing an application's look-and-feel. And since new resource values do not take effect until the application is restarted, they are not a very useful tool when prototyping an application with dtksh or Tcl/Tk. Indeed, though Tcl/Tk supports X resources, the documentation explicitly recommends against using them.

In MetaCard, the term "properties" is used to refer to these settings, which can only be set from the scripting language. During construction of the interface in MetaCard, properties are set using properties dialog boxes. These properties dialogs and menus are just MetaCard stacks and have no special relationship with the objects whose properties are being set. They just execute MetaCard scripts to change the properties. For example, to set the text displayed in the Font Name button, the following script is used:

set the label of button "Font Name" to "Helvetica"

Event Handling

Nearly all GUI toolkits have an event driven architecture. Each time the user of the application does something, whether it is typing on the keyboard, moving the mouse, or clicking with one of the mouse buttons, events are sent to the application.

In Tcl/Tk and dtksh, the events are handled by callbacks. The callbacks are functions in the scripting language that are attached to

the controls by executing a statement that binds the function to a particular event type. For example, the following dtksh statement binds the function selectCB to the event that occurs when a push button is pressed:


XtAddCallback $widget activateCallback "selectCB $widget"

The dtksh function that brings up a message box telling users what they clicked on can be declared as:

function selectCB {
   XtGetValues $1 labelString:name
   XtSetValues $MB messageString:"You clicked on $name"
   XtManageChildren $MB
}

In this example, $1 is the widget handle which passed in as the first argument due to the way the callback was added, and "Click Button Example" is the string put into the title bar of the dialog box. Note that you must get the name of the button in a separate statement, since the XtGetValues call puts the value into a variable ($name) rather than returning it. The MessageBox $MB must be created in the application initialization code.

In Tcl/Tk, two different methods of binding functions to events must be used. The most commonly used events have predefined options. For example, in the sample application the command option is used to specify a function that should be called when the style check boxes are clicked on. Less commonly used events must be bound to functions using the "bind" command. For example, there is no predefined option for catching a single click on a list box and so in the sample application the raw ButtonRelease-1 event on the list box must be bound to the resetFont function.

In MetaTalk, the MetaCard scripting language, events are called messages. When a message is sent, the script of the target object is searched for a handler for that message. For example, the following handler would be executed if it was in the script of a button and that button was clicked on. It opens a dialog box that displays the name of the object that was clicked on:

on mouseUp
  answer "You clicked on" && the name of the target
end mouseUp
When a message isn't handled, it is passed up the object hierarchy. For example, a message might be passed from a button to a group, which is MetaCard's container object. If it's not handled by the group, the message is passed on to the card and then on to the stack. The stack is often used to handle events that can be sent to any of the controls or cards in the stack. In the sample font chooser application, a single mouseUp message handler in the stack script handles the messages sent to all of the controls in the application.

On to Performance benchmarks

Back to Architecture of the GUI interface

Up to Table of Contents