## 5.4 A Language Prospectus and Comparison

Arguments about which language is best and why seemingly arise almost continuously. The next few paragraphs attempt to take a rational, if somewhat biased, look at why there are so many diverse opinions about languages. The apparent reason for this diversity is that different individuals have different needs and, in addition, they have backgrounds that predispose them toward one position or another. Outlined in the following discussion are a variety of concerns and issues and some opinions about the suitability of the various languages that have been presented for the problems indicated.

### Language Familiarity

Probably the single most important reason for favoritism of one language over another is prior familiarity and experience with a language. Computer languages require considerable study to learn. After learning a language almost no one wants to give up a comfortable set of knowledge to learn a new language even if it provides some additional features. Familiarity with the C language is clearly the primary reason for the high degree of success of C++ as an object-oriented language. During recent decades, AT&T made UNIX widely available to universities. Several generations of students have learned to use this operating system and its native language, C. Engineers often have a predilection for efficiency and speed, attributes of C-language implementations. No wonder that C has become very popular and is used worldwide for creating systems and applications. Hence, with a high level of interest in and knowledge about C among programmers trained in using UNIX, it is plausible that C++ would attract the attention of these persons. It would be less likely that this group would move to using entirely different environments such as Smalltalk.

### Task Suitability

A rationale methodology for selecting a language, apart from familiarity and experience, is the suitability of a language for achieving a task. Ultimately, the optimal computer language would be the one that solves the problems that one has with the least effort, most efficiency, and least time. Unfortunately, most problems that need to be solved all have different requirements and thus languages and environments with different characteristics will need to be employed. For example, tasks may require a high level of interactive use between the computer and human or may require large amounts of
computation. Obviously, slow but easy to use languages are unsuited for the
latter task, and vice versa. Thus, it is clear that task suitability must be a driver
in selecting languages and environments. Using this criterion, even languages
such as Fortran and C have a distinct place, for example, for number crunching.
Object-oriented languages have a niche in problem solving for tasks that permit
problem factorization into objects with behaviors. The paradigm results in a
reduction in complexity and simplicity in solving large problems.

Performance Issues

One potential criterion for choosing between languages and different
implementations of the same language is performance. Although execution
speed was once a criterion of paramount importance, this issue has almost
vanished as computer performance has increased and costs for expanded
computation power have decreased. Arguments for selecting languages for
problem solving based on performance are no longer important except for the
most intensive number-crunching requirements.

Memory Issues

In much the same way as the issue of performance, during recent
years costs for memory have decreased so significantly that making language
choices based on the amount of memory required is no longer considered except
for special applications (e.g., mobile equipment, consumer systems, etc.). Some
languages manage memory more efficiently and more automatically than others.
For example, Lisp and Smalltalk automatically collect garbage; that is, both
languages reclaim unused memory space made free by removing objects or
pointers that are no longer used. C++ and Objective-C require that the user
provide explicit memory management code.

Graphics Issues

Graphics have become increasingly important during recent decades.
Inexpensive moderate-resolution graphics capabilities can now be found on
most workstation and PC-level computers. Hence, languages that can make use
of hardware capabilities are almost mandatory. Most languages have added
graphics through the addition of graphics calls in the form of libraries. Exam-
ples are found in Fortran libraries for data presentation, libraries of C routines
to drive graphics displays, and CAD packages that have built-in graphics drivers
that directly support application code. Other languages, such as Smalltalk, were designed around specific graphics user interface concepts that enabled every user interaction to be accomplished through the graphics interface.

## User Interface Issues

The most common user interface since the 1960s has been the command line interface, in which users issue commands to an operating system after a prompt symbol displayed on a screen. Early efforts to move to graphics user interfaces met with cost problems due to the high expense of the graphics hardware required. Now, however, costs have declined to the point that it is likely that graphics "point-and-click" user interfaces will probably become the norm for the 1990s. Evidence for the growing influence of these types of interfaces is commonly observed in the Macintosh interface, Microsoft Windows, OS/2 PM, SunViews, the NeXT interface, and others [see, e.g., Brown and Cunningham (1989)]. Although some of these interfaces operate almost like a graphics translation of a command line interface, others capitalize on visual metaphors to provide additional capabilities. Computer languages can be an integral part of such capabilities, providing direct methods for manipulating user interfaces. If an application that is to be written requires a high degree of user interface support, creation of the application is likely to be much easier using a language that contains strong support for manipulating the interface.

## Portability Issues

Portability of code from one machine to another has become an issue due to the many different types of hardware platforms that are available. Traditionally, to port software from one machine to another, a requirement has been to modify the source code that runs on one machine to the requirements of another machine. For example, a Fortran program that runs on one machine will not usually run on another manufacturer's hardware and compiler. C, however, was designed to be fairly portable. Most C code can be moved in source form from one hardware platform to another. The same is not true of libraries, of course, that require use of different input/output (I/O) ports, screen drivers, and so on. Smalltalk-80 has the outstanding capability of being able to move, intact, complete images between different hardware platforms. The way that this capability was secured was to produce different implementations of the basic parts of Smalltalk (the virtual machine) for a number of different hardware platforms. Small and simple, the virtual machine provides the capability for supporting the remainder of the Smalltalk system, written in
Smalltalk itself. Given this capability, Smalltalk can be characterized as the most portable language and environment.

## Training Issues

In building applications, the tendency is to select, as indicated previously, the most familiar language available. However, the presence of skill in a language that is basically unsuitable for the required task may doom a project to failure. If one turns to more suitable languages to creating applications, the issue of training appears. How long does it take to learn a new language? What does the learning curve look like? How much material needs to be mastered before productive work can occur? The answers to these questions appear to be different for all the languages mentioned in this chapter but are directly proportional to a user's experience with a given language and with analogous languages. For example, a C programmer will have no difficulty learning Fortran or Pascal because the differences between the languages are relatively slight. Similarly, a Smalltalk-80 programmer can learn Smalltalk/V or Actor with little additional effort. However, the learning curve for a Fortran or C programmer to learn the substantial object-oriented languages remains flat for a long time. For languages that simply add basic object methodologies, such as C++ or Flavors, learning the basic object-oriented additions to the language occurs fairly rapidly. For Smalltalk, Actor, Objective-C, and languages that have class libraries and added facilities, the learning curve is much longer due to the requirement of learning how the classes work. What is the trade-off? The trade-off is that language syntax is usually fairly easy to learn and productive work can commence after a modest time investment for the basic object-oriented languages. The most complex object-oriented languages require a longer learning time but the payoff is a much higher level of productivity when training is complete. Figure 5.1 shows a hypothesized learning curve for some of the languages discussed in this chapter. It should be emphasized that this family of curves is not supported by any hard data and is based only on observation, anecdotal information, and experience. As shown in the figure, the traditional languages require a modest learning time to achieve moderate levels of productivity; the true object-oriented languages take longer to learn but result in higher levels of ultimate productivity. The time on the abscissa of the figure represents months of about half time devotion to study of the language. Of course, times vary considerably by individual. Testing to validate these hypothesized curves would require extensive efforts and, indeed, may not even be possible. However, it is believed that the general information shown has some comparative validity.
<figure><img src="image_56.png" /><figcaption>**Figure 5.1** Time versus Productivity for Several Languages.</figcaption></figure>

## Reusability

The key to productivity is reusability. The easiest way to produce code is obviously to have it already! The next easiest way is to specialize slightly the code that you have. Having an extensive class library permits rapid creation of new classes by inheritance as discussed in Chapter 2. High productivity results in being able to create new classes without having to produce new code continuously. Of course, the major drawback of having a large class library is having to understand the contents of the library, a quite formidable task, particularly in systems with large libraries such as Smalltalk-80. Table 5.6 compares the number of classes that are currently provided with the four major commercial object-oriented languages: Smalltalk-80, Smalltalk/V, Objective-C, and C++. As is evident from Table 5.6, the number of "built-in" classes varies from over 330 for Smalltalk-80 to none for C++. Objective-C permits purchase of additional classes to support user interface creation.

<table><caption>**Table 5.6** Classes Provided in Object-Oriented Languages (in 1991)</caption><thead><tr><td>Name</td><td>Number of Classes</td></tr></thead><tbody><tr><td>Smalltalk-80 (Release 4)</td><td>~ 330</td></tr><tr><td>Smalltalk/V (Windows version)</td><td>~ 175</td></tr><tr><td>Objective-C</td><td>> 20</td></tr><tr><td>extension</td><td>> 60</td></tr><tr><td>C++</td><td>0</td></tr></tbody></table>
## Ease of Programming

Language tools that assist in developing application programs are a consideration in selecting a language. Traditional programming languages have typically used the edit-compile-debug loop; that is, the user creates a source file of program text using a text editor of some type, compiles the source file, and then debugs the program by examining what errors occur when an attempt is made to run the program. Sophisticated compilers assist this process by doing extensive checking during compilation to assure the types are the same and that syntax is correctly followed. Furthermore, debuggers for some languages are available that permit single-stepping through a program to determine errors in logic. The most sophisticated tools provide this type of facility in a packaged way that assists the user in debugging program code. The more facilities that a debugger provides, the more rapidly application programs can be developed. Interpreted languages provide more flexibility than compiled languages because the code can be debugged on a line-by-line basis without having to go through the edit-compile-debug cycle. However, the drawback to interpreted languages are that they are much slower than compiled languages because additional time is taken up in the interpretation process. A good intermediate methodology is incremental compilation where the code is compiled in small increments. Hence, changes in any part of the program can be made easily and the behavior of the code traced easily, yet there is little speed penalty to making changes in the code. Smalltalk-80 uses this latter technique.

## The Importance of an Environment

An environment is a collection of tools that provides support for the programmer. There are various examples of environments; for example, in Lisp one of the first environments was the InterLisp environment (Teitelman and Masinter, 1981), LOOPS is another, and Smalltalk-80 is a third. The next chapter will discuss the ST-80 environment in detail. The importance of a good environment is that the programmer is provided with all the needed tools to develop applications—everything from code inspection, editing, debugging, and graphics to interface building. The desktop metaphor is a good one; that is, everything needed to build an application is within easy reach on the desktop.

## Issue Summary

Table 5.7 presents a summary of the features of the languages discussed in this chapter, segmented according to the characteristics just discussed.
<table><caption>Table 5.7 Language Feature Prospectus*</caption><thead><tr><th>Feature</th><th>Extension to Languages</th><th>Object-Oriented Languages with Classes</th><th>Traditional Languages</th></tr></thead><tbody><tr><td>Traditional programmer adaptability</td><td>High</td><td>Low</td><td>Very high</td></tr><tr><td>Performance</td><td>High</td><td>Moderate</td><td>High</td></tr><tr><td>Memory requirements</td><td>Low</td><td>High</td><td>Low</td></tr><tr><td>Training needs</td><td>Medium</td><td>High</td><td>Low</td></tr><tr><td>Productivity</td><td>Medium</td><td>Very high</td><td>Low</td></tr><tr><td>Reusability</td><td>Medium</td><td>Very high</td><td>Low</td></tr><tr><td>User interface support</td><td>Low</td><td>High</td><td>Low</td></tr><tr><td>Environmental support</td><td>Low</td><td>High</td><td>Low</td></tr></tbody></table>

*Extensions to languages: C++, Eiffel, Object Pascal, Flavors, CLOS; object-oriented languages with classes: Smalltalk, Actor, Objective-C; traditional languages: Fortran, C, Lisp, Pascal.

Language types are segmented into three different categories, as indicated in the table legend. An indication is given of the degree to which each group fulfills the criteria shown in the left column. Each characteristic is graded as low, medium, high, or very high. As one can see from this evaluation, the object-oriented languages containing class libraries are best in this type of evaluation. Doubtless the criteria used are flawed, but nonetheless should give an indication of how these different programming language categories differ in capability. If one were to assign numeric scores to the characteristics (e.g., low = 1 to very high = 4), one could obtain overall numeric scores. When this exercise is carried out, it is easy to see that language extensions provide some improvement over traditional languages, but languages with libraries of classes provide significant improvement.

## References

*Actor Language Manual* (1989). The Whitewater Group, Evanston, IL.

Birtwistle, G., O.-J. Dahl, B. Myhrlaug, and K. Hygaard (1973).

*Simula Begin*. Petrocelli/Charter, New York.

Birtwistle, Graham M. (1979). *A System for Discrete Event Modelling on Simula*. MacMillan, London.

Bobrow, D. G., L. G. DeMichiel, R. P. Gabriel, S. E. Keene, G. Kiczales, and D. A. Moon (1988). Common Lisp Object System Specification, X3J13 Document 88-002R, June.
Brown, J. R., and S. Cunningham (1982). *Programming the User Interface*. Wiley, New York.

Clocksin, W. F., and C. S. Mellish (1984). *Programming in Prolog*, 2nd ed. Springer-Verlag, New York.

CLOS. See Bobrow et al. (1988). and Keene (1989).

Digitalk, Inc., 9841 Airport Road Blvd., Los Angeles, CA 90045.

Eiffel, Interactive Software Engineering, Goleta, CA.

Franz, Inc., Alameda, CA.

Goldberg, Adele, and David Robson (1989). *Smalltalk-80: The Language*. Addison-Wesley, Reading, MA.

Iverson, K. (1962). *A Programming Language*. Wiley, New York.

Kay, Alan C. (1977). *Microelectronics and the Personal Computer*. *Scientific American*, September, 231-244.

Keene, Sonya E. (1989). *Object-Oriented Programming in Common LISP: A Programmer's Guide to CLOS*. Addison-Wesley, Reading, MA.

Kernighan, B. W., and D. M. Ritchie (1978, 1988). *The C Programming Language*. Prentice-Hall, Englewood Cliffs, NJ.

LaLonde, Wilf R., and John R. Pugh (1990). *Inside Smalltalk*, Volumes 1 and 2. Prentice-Hall, Englewood Cliffs, NJ.

Linton, M. A., J. M. Vlisides, and P. R. Calder (1989). *Composing User Interfaces with InterViews*. Computer, February, 8-22.

Lucid, Inc., Menlo Park, CA.

MacLennan, Bruce, J. (1983). *Principles of Programming Languages: Design, Evaluation and Implementation*. Holt, Rinehart and Winston, New York.

Meyer, B. (1988). *Object-Oriented Software Construction*. Prentice-Hall, Englewood Cliffs, NJ.

Moon, David A. (1986). *Object-Oriented Programming with Flavors. Object-Oriented Programming Systems, Languages and Application Conference Proceedings*. Association for Computing Machinery, Portland, OR, September, 1-8.

Objective-C, The Stepstone Corporation, 75 Glen Road, Sandy Hook, CT.

Papert, S. (1980). *Mindstorms: Children, Computers, and Powerful Ideas*. Basic Books, New York.

Pinson, Lewis J., and Richard S. Wiener (1988). *An Introduction to Object-Oriented Programming and Smalltalk*. Addison-Wesley, Reading, MA.

Saunders, J. (1989). *A Survey of Object-Oriented Programming Languages*. *Journal of Object-Oriented Programming*, Vol. 1, No. 6.
Simonian, R., and M. Crone (1988). *InnovAda: True Object-Oriented Programming* in *Ada. Journal of Object-Oriented Programming*, Vol. 1, No. 4, November/December, 1987, p. 21.

Schmucker, K. (1986). *Object Oriented Programming on the Macintosh*. Hayden Books, Hasbrouck Heights, NJ.

Snyder, Alan (1986). *Common Objects: An Overview*. *SIGPLAN Notes*. ACM, New York, 845-852.

Steele, Guy L., Jr. (1984). *Common Lisp, The Language*. Digital Equipment Corporation, Maynard, MA.

Stroustrup, B. (1986). *The C++ Programming Language*. Addison-Wesley, Reading, MA.

Teitelman, W., and L. Masinter (1981). *The Interlisp Programming Environment*. *Computer*, Vol. 14, No. 4, April, 1981, p. 25-34.

Turbo Pascal 5.5. Borland, Scotts Valley, CA.

UNIX Operating System. Western Electric, Greensboro, NC.

*User's Guide, Objectworks\Smalltalk*, Release 4 (1991). ParcPlace Systems, Mountain View, CA.

Weinreb, D., and D. Moon (1980). *Flavors: Message Passing in the Lisp Machine*. A.I. Memo No. 602, Massachusetts Institute of Technology, November.

## Exercises

5.1 From the subset of programming languages that you know, compare and contrast the features of the languages that you like and dislike based on the kinds of analyses used to evaluate languages in the chapter. Next, form class groups and argue about your findings. Do all of you agree? Or do you disagree? Why?

5.2 Study the information in Table 5.7. Do you agree with this information. If not defend your position.

5.3 Smalltalk syntax review exercises. This is a good place to stop and spend a day or two doing the ST-80 tutorials that are delivered with the ST-80 system from ParcPlace to get a feel for the language, if you have not done so already. The knowledge that you gain by doing these tutorials will be helpful in upcoming chapters.
<figure><img src="image_57.png" /></figure>
# Introduction to the ST-80 Environment

## 6.1 Environment Concepts

In general, an environment is something that surrounds. When used in the phrase *computing environment*, the term means something that surrounds the code that one works with; even more generally, it denotes the set of tools that are available to the user to manipulate programmatic code, text, images, or other more complex computational entities.

Operating systems and environments are somewhat similar terms: Both deal with the interface between the computer and the user. Operating system software provides the interface to the machine hardware and environments are usually built on top of operating system facilities. The phrase *operating system environment* connotes collections of utilities that a user of an operating system can employ. Most generally, an operating system is considered to be an integrated set of software that defines a basic set of operations that can be conducted on the computer hardware. Typical components of an operating system include code to manage multiple processes, a command line interface, memory management routines, and device drivers. Some operating systems permit only one process to run at a time (e.g., DOS) and others permit multiple processes (e.g., UNIX). Operating systems have evolved during recent decades from primitive systems that directly handled the basic computer operations to complex multitasking, multi-cpu systems that can support hundreds of users on one large computer. Systems with names such as VMS, DOS, OS/2, MacOS, OS/MVS, Multics, OS/360, UNIX, CP/M, and so on have been created to be used with various types of hardware. Students of operating systems study the architecture of operating systems, services, file systems, scheduling, memory
<table><caption>**Table 6.1** Components of the ST-80 Environment (Release 4)</caption><thead><tr><td>Characteristic Name</td><td>Definition</td></tr></thead><tbody><tr><td>System browser</td><td>Permits inspection and creation of code</td></tr><tr><td>File list</td><td>Access to the computer file system</td></tr><tr><td>Text editor</td><td>Creates text documents</td></tr><tr><td>*Terminal window</td><td>Connection to communications</td></tr><tr><td>*Form editor</td><td>Edits forms (bitmaps)</td></tr><tr><td>*Bit editor</td><td>Edits bits in forms</td></tr><tr><td>System workspace</td><td>Contains commonly used objects and messages for controlling system</td></tr><tr><td>Debugger</td><td>Used for correcting errors in code</td></tr><tr><td>System transcript</td><td>Displays messages from system</td></tr></tbody></table>

management, concurrent processes, and examples of different types of operating systems.

Environments have some of the same flavor of operating systems, although it is more usual to discuss "higher" level kinds of programmatic components, when describing the environmental characteristics of a system. For example, an environment might contain many integrated tools for achieving a certain goal. For example, a desktop publishing environment might consist of a text editor, a page layout program, and facilities for printing to a printer or typesetter. This set of facilities is an example of a special-purpose environment, designed for the purpose of surrounding the application, in this case, desktop publishing. To extend this limited view to the general environment for programming, there can be many kinds of tools that facilitate the programmer's chore, for example, code browsers, debuggers, code tracing and inspection facilities, editors, graphics facilities, and communications. This listing of tool names closely mirrors the actual integrated set of tools that are found in the Smalltalk-80 environment which will be described in detail in this chapter.

Table 6.1 displays a summary of the characteristics of the Smalltalk-80 environment and Figure 6.1 shows an example of the visual representation of environmental tools on the computer screen "desktop." The most prominent of the main components of the environment is the system browser, which will be described in more detail. In brief, this browser permits organization of information about the entire system. All classes and their methods may be examined and new classes and methods may be easily added to the system. The desktop provides tools that interface to the external environment, for example, the terminal window and the file list, which respectively permit communication and

<footnote>*Found only in Version 2.5.</footnote>
<figure><img src="image_58.png" /><figcaption>Figure 6.1 Screen Dump of Smalltalk-80 Screen.</figcaption></figure>
listing of files on disk. Text editing is provided with a built-in editor. A debugger is provided that has many capabilities including single-stepping through code and examining the values of the variables. The system transcript provides a place for messages from the system to be displayed and the system workspace contains useful objects and methods for working with the system components.

During 1990 and 1991, a major revision to Smalltalk-80 was made by ParcPlace Systems which added several significant features to the environment. The capability for displaying in color was added, as was the ability to run in windows of the host operating system. In Table 6.1, the characteristics of the ST-80 environment that are found only in Version 2.5 (the ST-80 release preceding Release 4) and earlier versions are denoted with an asterisk. For example, the terminal window feature was removed from the standard Release 4 and added to a supplementary set of Smalltalk-80 code called Objectkit \ Smalltalk. Classes from earlier versions that dealt with bitmaps were also removed and graphics classes added that are compatible with each host platform. Release 4 provides a high level of integration with every host platform. Perhaps most interesting is the capability for moving application code from one host platform to another (e.g., from Macintosh to Sun, or from DEC to PC) without having to change the code. In each case, the application will run on each different platform, adopting its "look and feel" to the characteristics of the user interface of the given hardware platform.

## 6.2 Characteristics of the ST-80 Graphics User Interface

Figure 6.2 shows the relationship between the mouse and the display of graphics interface items on the screen. A cursor, represented as an arrow pointing to the northwest, is linked to the movement of the mouse. Pressing mouse buttons with different combinations of key presses will cause different operations on the screen. Depending on the host windowing system, button presses will result in different actions. For example, on the Macintosh, the cursor can be used to activate different icons in the window label that close, iconify, or zoom the window. On the PC version, Microsoft Windows provides essentially the same features but with a slightly different look and feel. Each host window has a slightly different way of dealing with the operation of the host window. Inside a Smalltalk-80 window, holding down the left mouse button (the "select" button on a two-button mouse; also the single Macintosh button) and moving the cursor over text will highlight the text (i.e., change the background color). This context sensitivity is a key to the operation of the cursor/mouse combination; that is, the mouse buttons will perform different activities depending on where the cursor is located on the screen. Hence, one requirement for the system is to keep track of where the cursor is, both inside a window
<figure><img src="image_59.png" /><figcaption>**Figure 6.2** Context-Sensitive Menus: Different menus are activated by the mouse depending on the location of the cursor on the screen.</figcaption></figure>

and with respect to icons on the window that control window moving, sizing, and closing.

Mouse pointing devices can have different numbers of buttons: one, two, or three. For three-button mice, the left button (known as the *select* button) is used to make selections from text, point to items to select, or choose windows. The middle button (the *operate* button) pops up specific menus related to the application. The right button (the *view* button) deals with standard operations such as sizing, moving, or closing a window. Two-button mice have *select* and *view* allocated to the left and right buttons; pressing both buttons at once yields the *operate* activity. One-button mice, such as on the Macintosh, require that either a keyboard key be pressed to obtain complete mouse functionality or that the user activate the desired menu by pressing an icon on the screen.

Table 6.2 shows some of the prominent characteristics of the user interface for Smalltalk-80. Several visual cues are provided to assist the user: Different icons for cursors are employed, for example, the pointer icon for pointing to things, the hourglass icon to indicate waiting for something to happen, and text highlighting which assists in editing and executing code. The interface to the system is via the mouse and the keyboard. Probably well over 90 percent of user interaction with the system can be via the mouse except for
<table><caption>**Table 6.2** Characteristics of the ST-80 User Interface</caption><thead><tr><th>Characteristic</th><th>Comment</th></tr></thead><tbody><tr><td><strong>Visual Cues</strong></td><td></td></tr><tr><td>Cursors</td><td>Various cursor icons are used</td></tr><tr><td>Text highlighting</td><td>Text can be highlighted for changing, deleting, moving, executing</td></tr><tr><td><strong>User Interface</strong></td><td></td></tr><tr><td>Mouse</td><td>Multibuttoned/single-button mouse</td></tr><tr><td>Keyboard</td><td>Limited keyboard interaction needed and permitted</td></tr><tr><td><strong>Windows</strong></td><td></td></tr><tr><td>Rectangular screen areas</td><td>Resizeable, moveable, collapsible windows</td></tr><tr><td>Views</td><td>Views of various types, e.g., lists, images</td></tr><tr><td>Text</td><td>Text operations with different styles, fonts</td></tr><tr><td><strong>Menus</strong></td><td></td></tr><tr><td>Pop-up</td><td>Single lists to select from</td></tr><tr><td>Hierarchical</td><td>Treed lists</td></tr><tr><td><strong>Buttons</strong></td><td>When cursor is in button rectangle, pressing a mouse button causes an action</td></tr><tr><td><strong>Graphics</strong></td><td>Standard drawing methods: lines, polylines, wedges, rectangles, etc.</td></tr></tbody></table>

entering code as text via the keyboard. Windows are the basic medium for presenting different views. Windows can contain a view with a single thing, such as text or a list from which a selection can be made, but more commonly they contain multiple tiled views which represent all the elements needed for a complete application. The views that are displayed in windows are created through a process of specifying each view size, the view characteristics, and where it should be placed in the window. Standard menus consist of several types, for example, pop-up menus from which items can be selected and hierarchical menus that pop up and present multiple items in the form of a hierarchy. Buttons represented as checkboxes, radio buttons, rectangles, or words are mouse sensitive, and when pressed (i.e., moving the mouse cursor to the item and pressing the button on the mouse) can be used to initiate an action.

In the lower right corner of Figure 6.1 is a list called the Launcher which provides top-level control to the user of ST-80. In this example, all the tools on the desktop can be accessed by simply moving the mouse cursor to a selection and clicking the *select* mouse button on the line with the item name and the arrowhead. For each of the categories shown, another list of items
<table><caption>**Table 6.3** Partial Class Hierarchy of Smalltalk-80 (Release 4)</caption><thead><tr><th>Object</th><th>Magnitude</th></tr></thead><tbody><tr><td>Behavior</td><td>Magnitude</td></tr><tr><td>ClassDescription</td><td>Arithmetic Value</td></tr><tr><td>Class</td><td>Number</td></tr><tr><td>Metaclass</td><td>Fraction</td></tr><tr><td>BlockClosure</td><td>Integer</td></tr><tr><td>Boolean</td><td>Character</td></tr><tr><td>False</td><td>Date</td></tr><tr><td>True</td><td>Time</td></tr><tr><td>Collection</td><td>Model</td></tr><tr><td>Bag</td><td>Browser</td></tr><tr><td>MappedCollection</td><td>Debugger</td></tr><tr><td>Palette</td><td>PopUpMenu</td></tr><tr><td>Color Palette</td><td>StringHolder</td></tr><tr><td>Coverage Palette</td><td>ProcessorScheduler</td></tr><tr><td>Sequenceable Collection</td><td>Rectangle</td></tr><tr><td>Arrayed Collection</td><td>SharedQueue</td></tr><tr><td>Array</td><td>PeakableStream</td></tr><tr><td>Character Array</td><td>Random</td></tr><tr><td>String</td><td>VisualComponent</td></tr><tr><td>Text</td><td>Icon</td></tr><tr><td>Interval</td><td>Image</td></tr><tr><td>LinkedList</td><td>Depth1Image</td></tr><tr><td>Semaphore</td><td>Depth2Image</td></tr><tr><td>Ordered Collection</td><td>Depth4Image</td></tr><tr><td>Set</td><td>Depth8Image</td></tr><tr><td>Dictionary</td><td>Depth16Image</td></tr><tr><td>Controller</td><td>Depth24Image</td></tr><tr><td>Controller With Menu</td><td>Visual Part</td></tr><tr><td>List Controller</td><td>Composite Part</td></tr><tr><td>Section In List Controller</td><td>Dependent Composite Part</td></tr><tr><td>Paragraph Editor</td><td>Browser View</td></tr><tr><td>Text Controller</td><td>Dependent Part</td></tr><tr><td>Code Controller</td><td>View</td></tr><tr><td>Standard System Controller</td><td>Boolean Widget View</td></tr><tr><td>Delay</td><td>Labeled Boolean View</td></tr><tr><td>Filename</td><td>Fractional Widget View</td></tr><tr><td>Dos Filename</td><td>Launcher View</td></tr><tr><td>Mac Filename</td><td>Identifier View</td></tr><tr><td>Unix Filename</td><td>Scrolling View</td></tr><tr><td>Input Sensor</td><td>Scrolling Lines View</td></tr><tr><td>Window Sensor</td><td>List View</td></tr><tr><td>Input State</td><td>Selection In List View</td></tr><tr><td>Look Preferences</td><td>Edge Widget</td></tr><tr><td></td><td>Menu Bar</td></tr><tr><td></td><td>Scroller</td></tr><tr><td></td><td>Wrapper</td></tr></tbody></table>
appears from which the desired tool can be selected. Lists of selections are
easily tailored to add new selections that can be used to launch (i.e., "run") user
applications.

6.3 The Class Library

One of the most important aspects of ST-80 is the existence of a class
library consisting of more than 330 classes. Table 6.3 displays an abbreviated
ST-80 class hierarchy from Smalltalk-80, Release 4. The classes shown are not
the complete class library; only some of the more important classes are dis-
played here. This class hierarchy shows many of the classes that are discussed in

<figure><img src="image_60.png" /><figcaption>Figure 6.3 A Partial Class Hierarchy of the ST-80 System.</figcaption></figure>
the remainder of this text. The reader is referred to the ST-80 system itself to browse the classes and read the accompanying comments. To secure an idea of the evolution of ST-80 classes, the book by Goldberg and Robson (1989) and the two-volume text by Pugh and LaLonde (1990) are recommended for further reading. The presentation methodology in this table is that successive indentations from the left side of the page indicate subclasses; for example, **Character** is a subclass of **Magnitude**, which is a subclass of **Object**. Figure 6.3 shows a partial presentation of a portion of an abbreviated ST-80 class hierarchy in a treelike form. In Release 4 of ST-80, the graphics presentation classes have changed; Figure 6.3 indicates where there have been significant class changes by showing a dotted box around classes that were present in ST-80, Version 2.5 and earlier. Note that for backward compatibility, the **DisplayObject** and subclasses from earlier (i.e., Version 2.5) releases were retained in initial releases of Objectworks \ Smalltalk, Release 4. The characteristics of classes used for display in Release 4 of ST-80 will be described in some detail in Chapter 7.

**Magnitude**, **Collection**, **Stream**, and **View** classes rank among the most used in the ST-80 environment, particularly the various subclasses of these abstract objects. Probably the best way for the novice ST-80 user to become acquainted with these classes is to use the browser to examine the class hierarchy and the methods that are in each class. The methodology for using the browser is presented next.

## 6.4 Standard ST-80 Tools

### The Browser

The most important tool in the ST-80 environment is the system browser, which permits browsing the classes and methods in the class hierarchy. *Browsing*, in general, means to look through casually. In terms of browsing software, the intent of a browser is to permit the user to examine the code in an easy and straightforward manner. For ST-80, the system browser is really much more than a code examiner, providing capabilities for adding new classes and methods, finding classes, displaying hierarchies of classes, and generally organizing the user's work. Figure 6.4 displays a screen dump (i.e., an exact rendition of the way the screen looks) for the system browser. Shown across the top of the browser are four scrollable lists: the leftmost list contains *categories*, which give the user the capability of organizing classes into meaningful categories. Most often, users will use one or more categories for putting together an application. Associated with this view is a pop-up menu that permits adding, renaming, or removing categories. The second list from the left contains the name of the
<figure><img src="image_61.png" /><figcaption>Figure 6.4 The System Browser.</figcaption></figure>

classes that are in the category selected in the leftmost list. Separation of classes by category, in this way, permits easier inspection. The next list to the right is a list of *protocols*, which records logical groupings of names of methods associated with the class selected in the view to the left. Finally, in the rightmost view is found the *methods* list which includes the names of all the methods in the protocol selected. Shown in the large view at the bottom of the browser is the code of any method selected in the methods list. Also, displayed just below the class list are two buttons for selecting instances or classes. If the instance button is selected, then selections made in the protocol and methods lists refer to instance methods; if the class button is selected, then selections refer to class methods. This distinction is important and is frequently missed by novice Smalltalk users. The use of the browser to create an application will be covered in the following discussion.

## The Text Editor

Text may be almost intuitively edited using the text editor. The text editor is invoked by simply selecting *file editor* from the system menu. The user
<figure><img src="image_62.png" /><figcaption>Figure 6.5 The Text Editor.</figcaption></figure>

can size the window, type information into the window, and store the text in a file. Figure 6.5 shows a text editor window that contains different font sizes and styles. The pop-up menu that is invoked by the operate button is shown. Capabilities such as copy, cut and paste, underline, and save are the fundamental features of the editor. Highlighting text and then using these commands are sufficient for most needs, including rearranging words, sentences, and larger bodies of text.

## Images

Images are pixel-based rectangular areas that display images on the screen. In ST-80, Release 4 and higher, images support a general protocol for color graphics. The number of bits per pixel, which determines the number of colors that can be displayed, can be 1, 2, 4, 8, 16, or 24. In earlier versions of ST-80, only bitmapped black-and-white images, called forms, were supported. Images from standard drawing packages on most platforms can be directly imported into Smalltalk.

## The Form and Bit Editors

A form is a one-level image; that is, a form displays only black-and-white pixels in a rectangular area. Until the release of Release 4 of Objectworks \ Smalltalk by ParcPlace Systems in 1990/91, forms were the predominant medium on which Smalltalk programmers displayed images. A
description of forms and form manipulation capabilities is included here for backward compatibility. In Release 4 and higher, forms and bit editing capabilities have been removed in favor of using images. However, simple methods exist for translation between images and forms.

Figures 6.6 and 6.7 show examples of the form editor and the bit editor used in Version 2.5 and earlier releases of ST-80. The form editor had capabilities for creating simple drawings using the form tools that were iconically arrayed across the bottom of the form editor. The methodology employed was to use the bracket selection button, at the top left, to select a cursor from anywhere on the screen. The technique used was to bracket the area of the screen that would become the cursor with left and right brackets, activated by sequential mouse clicks. To create a small icon for drawing, a dot somewhere on the screen could be bracketed. Drawing was accomplished by using the single-point mode, multiple points, and straight or curved lines. The icon on the lower left button provided access to the bit editor to permit changes to be made in individual bits. The arrows at the right were used for input and output. Note that when the output arrow (lower right) was pressed, the form stored was the cursor selected by the angle bracket selection. This point was difficult for novice users to understand. Some users changed this feature of the form editor to store the entire image that was being edited. Although this change made logical sense, the original method of storing the cursor bracket was reasonable from the standpoint of being able to store forms of different parts of an image. A typical way to work with the form editor was to create several instances of the form editor and to paste information between editors. A favorite technique for annotating a picture was to type text in a workspace, bracket the text with the angle bracket to create a cursor of the text, and deposit the text in the target-image.

The bit editor, as shown in Figure 6.7, provided an expanded view of the bits in a small part of a form. In this example, the bit editor for the standard cursor, control was very simple. The user had only the choice of selecting a black or white pixel switch at the bottom of the view. Once one of these buttons was pressed, the color of each pixel could be changed by moving the cursor to an individual pixel and pressing the select button.

Creating forms by hand is, of course, not the only way to secure bitmapped images in Smalltalk. Perhaps the easiest methodology is to use a scanned image and directly import the image into ST-80. This capability in Release 4 has proved to be very popular and is a significant improvement over the Version 2.5 bitmap editing capabilities.

For Release 4 and higher, the comments made previously about bit editors and forms are obsolete. For these releases, images replace forms and either commercial drawing packages or the internal graphics methods of ST-80 can be used to create graphics. However, in 1991, no extensive color graphics editors existed for Objectworks \ Smalltalk.
<figure><img src="image_63.png" /><figcaption>Figure 6.6 The Form Editor.</figcaption></figure>
<figure><img src="image_64.png" /><figcaption>Figure 6.7 The Bit Editor.</figcaption></figure>

## Workspaces

A workspace is a window in which one can type in code and try out code prior to committing the code to a class. There are two workspace selections in the Launcher: the system workspace and general-purpose workspaces. The system workspace is a workspace containing many expressions involving objects and messages that are used to operate specific things in the ST-80 environment. Normally, users employ the system workspace for remembering how to do something associated with the ST-80 system. Figure 6.8 shows a small portion of the system workspace. Throughout the workspace there are example messages to classes that help the user remember how to use many of the common classes associated with operating the system. It is useful to add to the system workspace common things that you do, or need to remember. If building a large application, it is also useful to create special workspaces that can be used to remind you at a later time about some problem that has been left uncompleted or simply to help you or others understand the application. The
<figure><img src="image_65.png" /><figcaption>Figure 6.8 The System Workspace.</figcaption></figure>

point of this discussion is that workspaces, in general, serve (1) as a kind of
temporary work area or scratchpad and (2) as a cognitive aid in remembering
what you are doing when programming. The system workspace serves the same
purpose, but for remembering things associated with the system. The capability
for easily accessing examples and making notes about applications created is
particularly useful in a personal computing environment in which programming
is done in sporadic sessions sometimes separated by long time intervals.

The Debugger

The ST-80 debugger is activated when an error occurs in executing
code or when the user types control-C on the keyboard. The most usual mistake
is sending a message to an object that is not one of the methods that the object
understands. When such an error occurs, a window indicating that an error
happened pops up; the user can then either "proceed" or "debug" (via a
pop-up menu listing these two options). Selecting "debug" produces a window
similar to the one shown in Figure 6.9. In the top part of the window is the
message stack in a scrollable list, filled with successively earlier message calls.
Selecting an item presents the code surrounding that message call in the text
view just beneath the top view. This code is cast in the context of the running
program with all variables set to the values in effect at the time of the message
send. Shown in the two small lists at the bottom of the view are the variables
and their values to the bottom right and the assignments of the current objects
to the left. The outstanding capability of the debugging window is that the user
can execute code with variables intact to trace very rapidly any problem that
<figure><img src="image_66.png" /><figcaption>Figure 6.9 A Debugger Window.</figcaption></figure>

occurs. Furthermore, corrections to the code can be made on the spot and the program restarted. These capabilities lead to very rapid program debugging.

## The File List

Figure 6.10 shows the file list capabilities of the ST-80 desktop. The user enters the file directory of interest in the top view and selects "accept" from the attendant pop-up menu. Files in the directory appear in the file list in the middle view. Information in the bottom view about the file size and modification date appear. Operating the pop-up menu associated with the middle view and selecting "get contents" permits viewing of file contents in the bottom view; selecting "filein" files the Smalltalk code in the selected file into the image. Once the code is filed in, the user can examine the code by opening a browser or should select *update* in the category list of the browser to be able to browse newly filed-in classes in an already open browser.

## Other Facilities

There are a number of other facilities on the ST-80 desktop not explicitly described in the preceding discussion. For example, the projects
<figure><img src="image_67.png" /><figcaption>Figure 6.10 The File List.</figcaption></figure>

facility allows a user to “clear his desktop” for another project, while retaining the desktop contents for a current project. In this way, the user can move between various different projects that are each tailored to a specific environment.

## 6.5 Creating Applications Using the Smalltalk Environment

The first step in creating a new application in the ST-80 environment is to create a system browser from the Launcher. In the browser, in order to add a new class, one selects a category in the category list of the browser to put the class in; or, alternatively, one creates a new category using that selection in the pop-up menu associated with the category list. At this point, the window will appear similar to the window shown in Figure 6.11. Using the text facility, the user defines the superclass name, class name, instance, and class variables, and selects “accept,” according to the format displayed in the bottom text view of
<figure><img src="image_68.png" /><figcaption>**Figure 6.11** Creating a New Class.</figcaption></figure>

the browser. In this format, placeholders are provided which should be replaced with the names of the class and variables to be created. For example, in Figure 6.11 “NameOfClass” should be replaced with the name of the class being created and “NameOfSuperclass” should be replaced with the name of the superclass of the class being created. Similarly, class and instance variable names should replace the placeholders “ClassVarName1 ClassVarName2” and “instVarName1 instVarName2.” If the class being created is not identified with any particular superclass, for example, **Dictionary**, **OrderedCollection**, and so fourth, then the class to use for “NameOfSuperclass” is **Object**. As an example, a new class named **Car** might be created using this technique; after editing, the lines shown in the text window of Figure 6.11 would look like:

```
Object subclass: Car
    instanceVariablesNames: 'wheels enginetype horsepower style model'
    classVariableNames:"
    poolDictionaries:"
    category: 'Moving Vehicle Category'
```

In this example, there are no class variables and no pooled dictionaries (dictionaries accessed by different objects) and the class has been entered in the category 'Moving Vehicle Category.' The final step in creating the new class description is to select "accept" from the pop-up list in the text window.
The next step in the class creation process is to add methods to the class being created. The first step in this process is to add the names of protocols used in the protocol list. For each protocol, there can be any number of methods associated with the protocol, the names of which are displayed in the rightmost list view in the system browser window. To create a method, the technique is, after the protocol is named and selected, to type the method code into the text view with the method name on the first line. After completing entry of the method, selecting "accept" in the text view will add the method to the class and the name of the method added will be displayed in the browser window. After "accepting" code, the syntax of the code is scrutinized by the complier and the user notified if syntax problems are detected. Note carefully, that instance and class methods are entered separately according to the setting of the class/instance switches set in the browser.

## Running and Debugging

Once code has been entered, either partially or completely, testing and debugging can begin. Normally, the user places in the *open* method in the application view a message on how to run the application. For example, a class called `VCircuitSimView` could have a class message called *open* which might appear as

```
open
    "VCircuitSimView open"
... the method code for opening the view...
```

The quoted string is an executable comment with which the user can run the application. The way to use an executable comment of this type is to move the cursor to the beginning of the quoted character string and double click. This action highlights the text; popping up the action menu and selecting "doit" then sends the message *open* to the class *VCircuitSimView*. The application runs or else fails. In the latter case, a runtime failure will result in a debugger window popping up with a message across the top of the window and a text view containing the text of the code where execution ceased. Selection of two alternatives is possible at this junction: "proceed" or "debug." Selecting the latter produces a window similar to the one shown in Figure 6.12, containing the error message at the top, the stack of message sends next, the text of a selected message send, and finally two lists of variables and classes present, if any. In this example, an error was introduced in the "open" code to illustrate one of the most common errors. The text string just below the debugger window in the text window of the file list *DrawingView new init* was executed after *open* was sent to *DrawingView*. The debugger appeared and indicated that the message was not
<figure><img src="image_69.png" /><figcaption>Figure 6.12 Example of Fixing a Bug in a Debugger Window.</figcaption></figure>

understood. In this case, the error the user made was to use *init* rather than *initialize* as the message name for initialization; because the instance of class *DrawingView* that was created by sending *new* to this class did not have a method called *init*, the message *send init* failed. Probably this type of error is the most common, that is, trying to send a message to an object that the object does not understand. A second very common error is "subscript out of bounds" which is often found when the user attempts to access an element of a collection that does not exist.

## System State/Changes

The ST-80 environment provides a single-user personal computing environment. After using the environment (i.e., editing, adding classes, running applications, etc.), the user can select "save" from the system menu to save the current state of work as an image file. Novices should note that the ST80.im file
that is first opened should be saved with a personalized name (e.g., "myImage"). Upon reentering the environment using this name, the user reenters with an exact copy of the system that was saved. One can leave notes in workspaces to remind oneself about what was being done, as needed.

There exists an audit trail facility, known as "changes." The ST-80 system keeps track of each change made to classes, editing, and so on in a file with the same name as the image file with a .cha extension instead of an .im extension. Naturally, because all changes are saved, this profile becomes quite large after some time and should be compressed periodically to save space (Smalltalk condenseChanges). There is a change management browser that can be used to reconstruct changes to a system, if a system crash occurs, for example. An excellent discussion of these facilities is found in Goldberg (1984).

## Workspace Use

Workspaces are good for testing code. Quite often as one learns Smalltalk, code can be entered in a workspace and tested prior to entering a method in the system browser. It is sometimes convenient to name global variables in the workspace so that code can be executed and variables inspected while stepping through the code.

## Transferring ACOM Cards to the Browser

In Chapter 3, ACOM cards were created for the digital circuit simulation example. In subsequent chapters, this example will be completed

<table><caption>**Table 6.4** Steps in Transferring ACOM Cards to the System Browser</caption><thead><tr><td>Step</td><td>Example or Comment</td></tr></thead><tbody><tr><td>1. Select a name for the category</td><td>DigitalCircuitExample</td></tr><tr><td>2. Create classes:</td><td>Object subclass: AndGate</td></tr><tr><td>AndGate</td><td></td></tr><tr><td>OrGate</td><td></td></tr><tr><td>NotGate</td><td></td></tr><tr><td>Wire</td><td></td></tr><tr><td>3. Include the instance variables 'input output constraint' as shown on the cards</td><td></td></tr><tr><td>4. Name the protocols</td><td>e.g., initialize, access</td></tr><tr><td>5. Add the methods to each protocol</td><td>e.g.; for wire:<br>inputConnection:<br>outputConnection:<br>set:, etc.</td></tr></tbody></table>
along with all the methods. Given the information in Chapter 3, however, the information on the cards described can now be easily transcribed to the system browser. It is left to the reader to follow the steps given in Table 6.4.

Once the ACOM cards representing the model are transferred to the browser, the model-view-controller code for visually representing the model can be added to provide a visual interface to the code. The MVC methodology will be discussed in detail in Chapter 8 and a continuation of the digital circuit example will be given in Chapters 10 and 13.

## References

- Goldberg, Adele (1984). *Smalltalk-80, The Interactive Programming Environment*. Addison-Wesley, Reading, MA.

- Goldberg, Adele, and David Robson (1989). *Smalltalk-80: The Language*. Addison-Wesley, Reading, MA.

- Pugh, John R. and W. R. LaLonde (1990). *Inside Smalltalk, Volumes 1 and 2*. Prentice-Hall, Englewood Cliffs, NJ.

- Ritchie, D. M. (1979). *The Evolution of the Unix Time-Sharing System, Language Design and Programming Methodology*. Lecture Notes in Computer Science, Vol. 79, pp. 25-35. Springer-Verlag, Berlin.

## Exercises

6.1 Conduct experiments with each of the major components of the ST-80 system to make sure you understand how they work.

a. File list: Try examining code and filing in code. Specifically, make sure you can examine the contents of a file and that you can file Smalltalk code into the system.

b. System browser: Spend a lot of time browsing and examining classes. Try out the different options in the class menu. Try "inspect," "explain," "spawn hierarchy," and so forth. Describe the results.

c. Try adding additional categories to the Launcher. Explore **LauncherView** by using the system browser and see if you can add additional functionality to the Launcher.

6.2 Investigate the debugger. Run the code (i.e., highlight the code in a workspace and select "doit" with the operate button of the mouse) just below this problem and explain how the debugger and the system browser can be used to find and correct the error. While you are using
the debugger, investigate and explain what each of the views in the debugger are used for.

|j k|
j := 0.

Transcript show: (j + k) printString; cr.

(Hint: Try assigning a value to k and repeating the experiment.)

6.3 Actually type the ACOM cards for Chapter 3 into the system browser. Make sure that you understand how to organize categories, classes, protocols, and methods.

6.4 Try out the editing facilities in the "file editor." Type a paragraph, store the file, and retrieve it.
<figure><img src="image_70.png" /></figure>
# User Interface Design

This chapter discusses the general aspects of designing user interfaces. Moving from a broad viewpoint about the history and concepts of user interfaces to specific information about the implementation of displaying interface objects in ST-80, the information presented lays the groundwork for designing applications using the model-view-controller methods given in Chapter 8. Basic information relevant to ST-80, Release 4, display and view objects is presented. Also, Section 7.4 is devoted to compatibility between Release 4 and the previous version of ST-80 (Version 2.5). This information is presented for readers with prior knowledge of the display objects in the previous releases.

## 7.1 The User Interface

### User Interfaces

The term *user interface* can mean a variety of things in different contexts. For the purposes of this text, discussion will be limited to explication of interfaces between humans and computers. Perhaps some of the discussion will be relevant to creating other types of user interfaces as well, such as interfaces to instruments, cars, and other human-engineered artifacts.

For communicating with computers, two important factors are (1) communicating information to the computer from the user and (2) communicating information from the computer to the user. Consider Figure 7.1 which illustrates a conceptual distance between the user and the computer. Shown as an arrow from the user to the screen is the “command interpretation distance” and shown as an arrow from the screen to the user is the “screen interpretation distance”.
<figure><img src="image_71.png" /><figcaption>**Figure 7.1** The Conceptual Distances between User and Computer.</figcaption></figure>

distance.” These two distances conceptually illustrate the gap between the user and the interface. Ideally, if a user interface were wholly intuitive, the gap would be zero; that is, the interface could understand whatever the user “said” and the user could understand whatever the interface returned. Considerable effort has been made over the last two decades to close the conceptual gap between humans and computers. Since the early days of computing in which switches were directly manipulated on the console of a computer to input raw information, significant progress has been made to improve human-computer communication. The range of interfaces from command line interfaces to direct-manipulation interfaces will be examined next.

Primitive computers were programmed by setting switches on the front panel of the computer to load individual instructions into the machine. Then, to run a program, the operator would press a switch, perhaps labeled “run,” which would cause the program to be executed. This manual program entry and operation was, in fact, a kind of user interface, albeit very simple, primitive, and tedious to use. Subsequently, simple mnemonic interpreters were developed that could interpret simple commands, for example, “L” for load, “R” for run, and so on, which a user could enter on a keyboard or by feeding in paper tape. This progression toward more sophistication resulted in simple operating systems with direct and easy-to-understand commands that could be typed on a keyboard and observed when echoed on a screen or printer. Command line interfaces became the most popular interface for many years, consisting of sequences of typed characters that permitted the user to control the operating system by issuing commands such as “dir” or “ls.” The DOS and
<table><caption>Table 7.1 Examples of Commands Use in Command Line Interfaces</caption><thead><tr><td>Command Line Example</td><td>Description</td></tr></thead><tbody><tr><td>&gt; DIR /P/W \BIN</td><td>A DOS command for listing a directory<br>(/P = pause, /W = wide)</td></tr><tr><td>&gt; DIR|SORT &gt; PRN</td><td>Sorts a DOS directory and prints out</td></tr><tr><td>&gt; MODE COM1: 96,E,8,1,P</td><td>Sets the mode of a serial port (DOS)</td></tr><tr><td>%ls -al</td><td>Unix directory command</td></tr><tr><td>%stty cstopb ignbrk ixon evenp &gt; /dev/tty02</td><td>Sets the terminal characteristics of tty02 to two stop bits, ignore break, input xon, and even parity</td></tr></tbody></table>

UNIX operating systems both employ command line interfaces. Table 7.1 shows several examples of command line interaction, to illustrate simple and complex styles of interaction. The first character in each line of the example is the prompt character issued by the operating system.

As shown in Table 7.1, typical commands in command line interfaces are only somewhat intuitive. For example, typing the DOS "dir" is a somewhat intuitive command for making a listing of a directory. The attendant "switches" "/P and /W" are not intuitive and their meanings must be obtained from a manual. UNIX commands are generally even more obscure, for example, the command "ls" for making a listing of a directory. Note that these examples from two common operating systems use forward slashes (/) and backslashes (\) in directory paths to produce the same meaning, a convention certain to confuse a novice. If one understands and remembers UNIX and DOS commands, the commands shown most likely have meaning; however, a novice is absolutely lost, having no notion about what commands to issue when confronted with the system prompt. Indeed, the mnemonics have meaning only when used and associated with the actions that they perform. Yet, once learned, these mnemonics form an easy and direct way to communicate with an operating system.

The difficulty of learning to use command line interfaces initiated the transition to modern user interfaces that are heavily graphics and pointing-device oriented. Graphics and direct-manipulation interfaces will be examined next.

## Graphics and Direct-Manipulation Interfaces

### Graphics User Interface

A graphics user interface (GUI) is most popularly thought to be the type of interface that one sees on a Macintosh computer or on a PC using
Microsoft Windows; that is, a windowed screen environment with menus, icons, and so on that can be accessed using a pointing device. If the term is taken literally, any interface that employs graphics could be associated with this term. For example, a computer system that simply presents graphical information would qualify under this literal interpretation. In fact, there is a significant range of capabilities that is contained in most GUIs. Typical GUIs use windows; for example, X-Windows (Schiefler, Gettys, and Newman, 1989) is an interface that primarily supports one style of windows. However, a windowing system may support only window activities and not the remaining characteristics of GUIs such as mouse support, menus, and so on.

A graphics user interface should have (1) some type of windowing mechanism, (2) an imaging model, that is, a definition of how graphics are displayed on the screen, and (3) an application builder interface (e.g., routines that can be used by the user to build the interface). Common examples of GUIs include names like NewWave from Hewlett-Packard, Microsoft Windows, Open Desktop, NextStep, OS/2 PM, and the Mac GUI. These interfaces all have different windowing systems and imaging models and run with different operating systems. The most familiar imaging model is Postscript (Holzgang, 1988) which can be used for printing or, in the screen version, for display. Perhaps some particular model and windowing system will become dominant in the future. All GUI systems look similar to the casual user. All have windows and permit resizing, moving, and collapsing. Most have pop-up and/or pull-down menus and buttons, provide text windows with editing features, and allow control via buttons. The use of color varies; some systems provide color, whereas others do not.

## Direct-Manipulation Interfaces

The characteristics of GUIs become commingled with the definition of direct-manipulation interfaces. Shneiderman (1982) coined the term direct-manipulation interface and defined a DMI to have the following properties:

1. A DMI provides a continuous representation of objects.

2. Physical actions, rather than command line interfaces, are used to carry out operations.

3. Actions can be rapidly reversed with visual notification of the reversal.

This definition is more general than the rather specific attributes of GUIs listed previously, yet fits completely. A continuous representation of objects is manifested in a GUI as information in windows or icons which, when accessed or
activated, perform an action. The notion of physical actions rather than com-
mand line syntax is obviously implemented in the point-and-click metaphor
commonly found in GUIs. Finally, the reversal of actions and visual notification
are easily linked in the typical GUI format.

Hence, what is the difference between GUIs and DMIs? Really none,
if the GUIs employed have the capability to conform to the Shneiderman
definition. To make clear the intentions in this text, the term graphics direct-
manipulation interface (GDMI) is used to reflect the need to provide DMI
characteristics in the graphics interface.

Both hardware and software support are needed to implement graph-
ics direct-manipulation interfaces. Each category will be examined in the
following discussion.

Hardware Support for User Interfaces

Various types of pointing devices have been used to permit the user to
move a cursor on a screen. Examples include trackballs, joysticks, touch pads,
control panels, tablets, sensing of a pointing finger, light pen, and even sensors
on a gloved hand. The intention is the same for all cases: to provide the user a
natural and simple way to interface with the computer. How can one choose the
best way? Like evolution, perhaps natural selection is the best. Certainly during
recent decades each of these types of pointing devices has been promoted by
various advocates. Currently the mouse appears to be the most popular. Let's
see why.

Consider the use of a pointing finger or light pen as the pointing
device. Sensed by devices placed around the periphery of the screen or from
sensing the light on the end of a pen, the location on the screen at which the
finger or light pen was pointed could be sensed. However, this methodology
suffered from having the user actually point at the screen—a truly tiresome
task. Hence, this methodology has virtually disappeared.

The use of joysticks has also become less prevalent, perhaps because
of identification with video games, but more likely because of the cognitive
dissonance of moving a cursor on the screen with a device that feels like a
control for an airplane. The effect is that the use of the device does not match
the task. If the task was simulating an airplane, then the joystick would be the
most acceptable pointing device. The use of control panels separate from the
keyboard, for example, a panel with left, right, up, down buttons has also largely
disappeared due to the poor mating with the domain. Indeed, in current
graphics user interfaces, even the standard cursor keys on the computer key-
board play a minor role.

Thus, almost by default, the most suitable device emerges—the mouse,
and its cousin the trackball, which is essentially an upside-down mouse. The
trackball suffers from the problem that it is somewhat more difficult to use than a mouse. However, due to the increased popularity of portable computers and the requirement of having a flat surface on which to move a mouse, the trackball is becoming more popular. The primacy of the mouse/trackball probably came about because these types of pointing devices directly relate to the human pointing experience, are simple to operate, and are comfortable to use.

There still may be other modalities of interaction that may be useful which are yet to be invented. For example, sensors on gloves may provide a technique for pointing that would give multidimensional capabilities. This technique can be combined with binocular visual displays that would allow a user to become part of a virtual scene. There is currently little consensus on the utility of this display modality.

## Software Support for User Interfaces

As discussed previously, the mouse/window准icon user interface is the most popular style of interface in use. Most of the qualities of the interface (apart from the mouse) reside in the software created to support the interface. Most window-based systems have a similar "look and feel"; however, there are other types of interfaces for special applications that are distinctly different. For example, consider a spreadsheet application in which rows and columns are presented to the user with constraints (mathematical relationships) at cell used to represent interactions between numbers. This interface is very compelling for applications involving accounting-related applications. An important point is that the user interface design mimics, in a way that the user understands, paper-and-pencil spreadsheets used prior to the introduction of computer spreadsheets. In the same way, desktop publishing interfaces mimic the same type of environments that were found in traditional publishing and layout environments. Hence, software design of user interfaces has been most successful in transferring metaphors from the real world to the computer interface for special applications. It is straightforward to mimic traditional application methods (e.g., spreadsheets, publishing) of doing things in designing a computer-based system to do a similar task; however, it is more difficult to create a general-purpose user interface for assisting programming tasks. The window/mouse准icon methodology comes currently closest to a universal interface that can assist programming tasks. An important feature of software for building user interfaces is that it should be open, inspectable, and easy to tailor to different application environments. Criticisms of user interface building tools include such factors as difficulty of use, difficulty in understanding, and nonportability between platforms, all problems that would argue against use of an interface
building software system. It is the contention of this text that the ST-80 user environment provides a rich user interface building tool that can be modified for many different applications and can create most user interface characteristics desired. The model-view-controller paradigm provides a rich mechanism for coordinating the application data, controlling the pointing device, and organizing what is seen on the screen. Use of this model will be described in detail in Chapter 8.

## 7.2 Characteristics of Graphics Direct-Manipulation Interfaces

### The Graphics DMI

In this section, a framework for understanding issues surrounding design of graphics direct-manipulation interfaces will be built. The term GDMI is used in preference to either GUI or DMI because either by itself lacks the composite description; that is, a *graphics* direct-manipulation interface is the desired interface. Various researchers have studied direct-manipulation interfaces [see, e.g., Hutchins and Norman (1986) and Shneiderman (1982, 1983)]. Some of the ideas and terminology contained in these research efforts are used for the describing characteristics of GDMIs presented next.

### Closing the Gap between User and Machine

A fundamental principle in creating a user interface is to reduce the gap between the user and the machine. A desire is to make the operation of a computer system almost completely intuitive for the novice and, for the expert, to permit the system to be operated in efficient instinctive ways that do not hinder operation. An effective user interface should lower the cognitive overhead for naive users to the point that concrete actions result in concrete information being returned. Designing for both the novice and the expert is not trivial. Consider that a typical novice-oriented system must have information completely spelled out. Actions selected from button presses or multiple choices are needed to guide the novice from one step to another. An example would be the overly complex sequencing of steps in some word processors which require multiple sequences of operations to achieve a single conceptual step such as moving a paragraph from one location to another. Making the steps needed to perform an operation explicit is very useful for novices but is exceptionally annoying for the expert who desperately wants shortcuts to achieve actions
more efficiently. Ideally, an excellent user interface should adapt itself to the needs of the user so that such problems do not occur.

Two areas are considered next: the execution of commands and the interpretation of results. Commands are issued by the user and information distilled in some way is returned to the user. The combination of the execution gap and the interpretation gap represents the total distance between the user and computer. Closing the gap simply means making both the input of information simple and intuitive and the resulting information fed back to the user equally understandable. The gap is closed when all users, from novice to expert, feel that the interface is unobtrusive.

## Execution Gap

Line-oriented commands are not particularly intuitive. To execute a command to make a directory listing, one might type to a command line interpreter such commands as "dir" or "ls." How can a novice learn about such commands? There are two ways: by reading a manual or through assistance menus that provide an interface alias for the actual commands. The popularity of simple command line interfaces (e.g., DOS) among casual users of computer systems and the popularity of complex command line interfaces (e.g., UNIX) among experts points toward the following conclusions. Novices need simplicity and concreteness. Experts need flexibility and conciseness. These conclusions seemingly promote building different-style interfaces. The GDMI has the potential for satisfying these different needs. A visual interface can close the execution gap significantly by providing a concrete representation to the users of what to do in the form of graphic representations. Pressing a button marked "list directory" is significantly easier than reading a manual to determine that one should type "ls" at the command line prompt.

The conjecture that GDMIs narrow the execution gap would be more plausible if GDMIs were intelligent enough to adapt to the needs of the user automatically. Without careful design or adaptability, operation of GDMIs can become tedious for the expert.

## Evaluation Gap

This gap is the information presentation portion of the overall gap between the user and the computer system. A simple example of this gap is the contrast between the presentation of a table of numbers and a graph that presents the numbers and their graphic interpretation. The results of operations must be exposed and observable. Graphic organization of data and knowledge
are essential. For example, a long list of rules (e.g, if-then rules) is hard for a user to understand. When presented in the form of a tree hierarchy, however, the logic in rules becomes more understandable. The same notion is true of many interfaces. For example, the desktop publishing interface and many word processing interfaces present text as it will be seen on the final printed page (WYSIWYG—"What you see is what you get"), a powerful and useful technique that has made packages that use such interfaces very popular. Closing the evaluation gap requires careful thought about what the user should see, how the information should be packaged, and what flexible features should be available to permit inspectability without confusion. These are tough issues that remain largely unresolved.

## Concrete Representations

A technique for closing the execution/evaluation gap may be to move away from abstraction to concreteness in interface design. It is certain that command line interfaces are abstract. In other words, typing a specific command does not represent a concrete physical action; it is merely a sequence of characters that represents an abstraction for a physical operation. Pushing buttons with labels is also abstract, however. Yet, using labeled buttons on the screen has the advantage that potential actions are made explicit and thus concrete in the mind of the user. More concrete representations consist of icons that represent what one is intending to do in a concrete way. For example, grabbing a picture of a file and moving it to a picture of a garbage can might cause a user to think that the file was being discarded. There could be many kinds of graphics operations defined in this literal style. However, one must be careful to ensure that such literal graphics operations make sense so that in the context of the past experience of users, operations will make sense. For creating representations of the real world, iconified graphic representations make good sense; one can create, for example, simulations of factories, traffic flow, fluid flow, or electrical systems that have a high degree of conceptual correspondence to the real world. It is not clear if such clarity can be achieved for GDMIs for programming environments, however. The characteristics of GDMIs for programming environments have not yet been defined. Certain features are plausible candidates such as visually oriented debuggers, browsers, file inspectors, and editors. The interface capabilities of ST-80 point the way toward design of useful interface characteristics that can facilitate graphics system building and programming capabilities.

Figure 7.2 shows some of the common display objects used in the ST-80 interface. Shown in the figure are tiled and overlapping windows, icons, menus, and question boxes. Examine the icon that appears as a door; the
<figure><img src="image_72.png" /><figcaption>**Figure 7.2** Four Common Display Objects Used in ST-80.</figcaption></figure>

concept here is to provide an interface to various projects (i.e., different applications or work areas). By selecting "enter" from menus associated with different doors, various projects can be entered. Using multiple doors on the screen would provide a concrete cue to the user about what different applications are available in an environment. Tiled windows permit capturing in one unified window related and interacting information about an application. Similarly, separated windows provide some conceptual distance between activities that can be conducted on the computer desktop. The desktop metaphor relates to the analogy between multiple windows and multiple sheets or stacks of paper on a desktop. Lists provide a way of organizing alternatives to select from and in the case of hierarchical menus, permit organizing selections in tree form. Such hierarchical information imparts information to the user of the system simply by existing. Buttons and switches promote disclosure of operation information. Implicitly exclusive alternatives can be graphically delineated by so-called "push buttons" or "radio" buttons which, when one presses one button "on," the other buttons are turned "off." Using this visual cue, the user is informed about the causal nature of information that exists between these alternative selections.

The next sections commence the description of how to display things graphically in ST-80. Beginning with simple display techniques, discussing windows, examining specific design elements, and finally considering how to
tailor the user interface, these sections lead toward explicit implementation information for the model-view-controller paradigm given in the next chapter.

## 7.3 Visual Display Methods

This section gives an overview of how visual components are displayed in ST-80. The information in this section is specific to ST-80, Release 4 and later releases. For compatibility with earlier versions, the next section presents information about displaying objects in Versions 2.5 and earlier. Comments about similarities and differences in the display techniques used in two versions are made where appropriate.

The three basic display surfaces defined for Release 4 are windows, pixmaps, and masks. Windows are the rectangular display ports supplied by the host platform and managed by the host platform's window manager. For example, windows may be MS-Windows on PC platforms, X-Windows on HP and Sun platforms, and Mac windows on the Macintosh. When a ST-80 image is moved between platforms, the look and feel of the window that appears is that of the host windowing system. The information displayed in the window, however, does not change. AventMap is an off-screen graphics medium on which drawings can be constructed. In order to display in a window, drawings must be copied from theventMap to a display surface in the window. Masks are used for stenciling operations, that is, for permitting color to be copied to selected parts of the display surface.

### VisualComponent Hierarchy

Table 7.2 shows a partial class hierarchy for the class VisualComponent and some of its subclasses. VisualComponent is an abstract superclass, meaning that objects are never instantiated from it, but that it is used only as a class from which subclasses can inherit methods and variables. VisualComponent implements behaviors common to its subclasses including methods for moving images and determining whether a point is in the view. Some example subclasses include Image which captures multilevel bitmaps of sampled images, Icon which captures a bitmap to display when windows are collapsed, and an abstract class named VisualPart which has various subclasses for displaying visual information in views. CompositePart, DependentPart, EdgeWidget, and Wrapper are each subclasses of VisualPart that provide general information for concrete subclasses such as View, Dialog View, or different types of widgets.Widgets are simply additions to views that provide additional functionality, for
<table><caption>**Table 7.2** Partial Class Hierarchy for VisualComponent (Release 4)</caption><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Visual Component</td><td></td></tr><tr><td>CachedImage</td><td></td></tr><tr><td>DisplayObject</td><td>"Backward Compatibility"</td></tr><tr><td>DisplayMedium</td><td></td></tr><tr><td>Form</td><td></td></tr><tr><td>InfiniteForm</td><td></td></tr><tr><td>OpaqueForm</td><td></td></tr><tr><td>Icon</td><td></td></tr><tr><td>Image</td><td>{6 subclasses}</td></tr><tr><td>OpaqueImage</td><td></td></tr><tr><td>TextLines</td><td></td></tr><tr><td>VisualPart</td><td></td></tr><tr><td>CompositePart</td><td></td></tr><tr><td>DependentComposite</td><td></td></tr><tr><td>BrowserView</td><td></td></tr><tr><td>CompositeView</td><td></td></tr><tr><td>DialogView</td><td></td></tr><tr><td>DependentPart</td><td></td></tr><tr><td>View</td><td>{> 20 subclasses}</td></tr><tr><td>EdgeWidget</td><td>{5 subclasses}</td></tr><tr><td>Wrapper</td><td>{4 subclasses}</td></tr></tbody></table>

example, scrollers along the edges of views that permit vertical or horizontal scrolling. Wrappers implement additional view functionality, for example, adding borders to a view. As indicated in Table 7.2, there are several subclasses for **View**, **Widget**, and **Wrapper**. The best way to become acquainted with these classes is to use the system browser to examine the classes and to review the comments contained under the comment selection of the pop-up menu associated with the list of class names in the browser.

## Graphics Contexts

The class **GraphicsContext** holds information about how to display an object. For example, a graphics context would hold information about where to display, define the coordinate system, specify the rectangle within which to display, and give default values for paint selection, font type, line parameters, and so on. A graphics context can be obtained from a view by sending the message **graphicsContext** to a view. Messages within the class are available for accessing or setting the state of the graphics context. Hence, for example, one
<table><caption>**Table 7.3** Example Methods for Displaying Graphics Objects*</caption><tr><td>Displaying strings</td><td>displayString:from:to:<br/>displayString:at:</td></tr><tr><td>Displaying lines</td><td>displayLineFrom:to:</td></tr><tr><td>Displaying polylines</td><td>displayPolyline: aCollectionOfPoints<br/>displayPolyline:at:</td></tr><tr><td>Displaying rectangles</td><td>displayRectangle:at:<br/>displayRectangle: aRectangle</td></tr><tr><td>Displaying polygons</td><td>displayPolygon:at:<br/>displayPolygon: aCollectionOfPoints</td></tr><tr><td>Displaying arcs</td><td>displayArcBoundedBy:startAngle:sweepAngle</td></tr><tr><td>Displaying wedges</td><td>displayWedgeBoundedBy:startAngle:sweepAngle</td></tr><tr><td>Displaying images</td><td>displayImage:at:</td></tr></table>

can change the color or font of an image to display simply by sending the desired color or font to the graphics context of the image.

## Displaying Graphics Objects

Table 7.3 shows methods for displaying primitive graphics objects. Many of the messages shown are of the form `displayTHING: whatToDisplay` or `displayTHING: whatToDisplay at: whereToDisplay`. For example,

`displayPolyline: pointCollection at: aPoint`

is a method for displaying a line specified by a collection of points. The location at which to begin the display is to be specified in aPoint, which is relative to the window in which the polyline is to be displayed. All these display methods are to be sent to a graphics context which specifies the default display information as well as where to display the graphics information specified.

## Paint

Paint and its subclasses provide the capability for coloring graphics objects. The `ColorValue` subclass of `Paint` permits specifying a color by name, for example, `ColorValue red`. An alternative to naming a color is to specify a mixture of `RGB` (red, green, blue) values, when mixed together yield the desired color; for example, `ColorValue red: 0.2 green: 0.8 blue: 0.0`. A subclass of `Paint`,

<footnote>*Abstracted from ParcPlace Objectworks\ Smalltalk User's Guide, Release 4.</footnote>
**CoverageValue** permits specification of the degree of coverage, from opaque to transparent, of a specified area.

## Images

Images are pixel-based rectangular areas that are used to display graphics, both color and black and white. Most early versions of ST-80 were restricted to black-and-white images; ObjectWorks \ Smalltalk-80, Release 4, supports full color and integration with drawing platforms on host platforms. Images support color ranging from 1 bit up to 24 bits at each pixel, yielding color combinations from 2 to over 16 million. Of course, the proper graphics display device is needed to display color maps at high pixel depth. To understand how images are represented, consider the simplest case first. A rectangle of 100 by 100 pixels could be specified for displaying an image with only two colors, for example, black and white. An image of this size would consume only a small rectangle on a 640 by 480 screen. Each pixel would require one bit: a 0 to represent one color and a 1 to represent the other color. Consequently, to represent the entire image matrix, a total of 100 \ 100 \ 1 bit = $10^4$ bits would be required. To increase the number of colors that could be displayed, the number of bits at each pixel can be increased; for example, to display 16 colors, 4 bits would be needed to uniquely specify each color, thus increasing the image matrix required to $4 \times 10^4$.

For the beginner, experimentation with images is simple. For example, in a workplace one could type:

```
|anImage|
anImage := Image from User.
```

highlight this code and select `doit` from the operate menu. Sending the message `fromUser` to **Image** results in display of a cursor on the screen that permits the user to bracket any section of the screen. The resulting captured image from the screen can be saved in a variable and then displayed in a window. For example,

```
ScheduledControllers activeController view graphicsContext displayImage: anImage at: 0@0.
```

will display the image stored in the variable `anImage` in the current active window at the top left corner of the window (i.e., 0@0). To try out the previous example, type the three lines of code beginning with `|anImage|` and ending with `... 0@0` into a workspace, highlight the entire code, and select `doit` from the pop-up menu.
Furthermore, an image captured in this way can be stored in a file using the binary object storage facility of ST-80. Perhaps most interesting is that users can employ common drawing packages to draw images or capture clip art from packages on the host platform that can be directly imported into the Smalltalk environment.

## Palettes

Palettes provide a way of interpreting the numerical pixel values in an image. Two main representations are used: a fixed palette in which the contributions of red, green, and blue to a color are specified and a mapped palette that stores a table of values corresponding to specific prespecified colors.

## Animation

The class **VisualComponent** provides a useful method called *follow: aLocation while: true on: aGraphicsContext* which can be used for animation. This message can be sent to an image (because **Image** is a subclass of **VisualComponent**) and the image will track the mouse location specified in *aLocation* as long as the argument to `while:` is true. Display is on the graphics context specified. Figures 7.3 and 7.4 illustrate the use of the *follow:while:on:* method for drawing a line on a view in a window. Figure 7.3 shows how to set

<figure><img src="image_73.png" /><figcaption>Figure 7.3 Code for Drawing on a View.</figcaption></figure>
<figure><img src="image_74.png" /><figcaption>**Figure 7.4** Example of Drawing a Line on a View Using Code in Figure 7.3.</figcaption></figure>

up a window and view (DrawView) on which to draw a line and Figure 7.4 captures the drawing of a line on the view. Note the use of `displayLineFrom/to:` and detection of the location of the cursor in the window by using `DrawView` controller sensor `cursorPoint`.

A simple technique for animation is a “filmloop” which is simply a collection of images repeatedly displayed at the same location on the screen. Using a drawing package, one could, for example, create about 30 images of a flywheel with an arm. By continuously displaying these images in order, with a delay of perhaps 1/30 of a second or less between the presentation of each image, the result will be an animation of a flywheel on the screen. For any continuous repeatable animation, the filmloop idea is a useful technique. Details on implementation of filmloops is given in LaLonde and Pugh (1989).

## 7.4 Backward Compatibility for DisplayObjects: Forms, Pens, and Paths

This section presents an overview of how a few simple objects in ST-80, Version 2.5 and earlier, were displayed. This section can be skipped by readers who are not interested in comparing the display methods used in earlier versions of ST-80 with Release 4. This information is presented for those readers who still have Version 2.5 or those who wish to gain a historical perspective about the influential graphics models that were used in Smalltalk-80 for almost 20 years. The display model in previous versions was significantly different from the display model for Release 4 described in the previous section. General display notions will be examined as well as the hierarchy of display objects and a few specific useful objects that can be used for building displays in this version of the ST-80 display model. The interested reader is referred to
<table><caption>**Table 7.4** Class Hierarchy for DisplayObjects (Version 2.5)</caption><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Object</td><td></td></tr><tr><td>DisplayObject</td><td></td></tr><tr><td>DisplayMedium</td><td></td></tr><tr><td>Form</td><td></td></tr><tr><td>Cursor</td><td></td></tr><tr><td>Display</td><td></td></tr><tr><td>DisplayText</td><td></td></tr><tr><td>Paragraph</td><td></td></tr><tr><td>InfiniteForm</td><td></td></tr><tr><td>OpaqueForm</td><td></td></tr><tr><td>Path</td><td></td></tr><tr><td>Arc</td><td></td></tr><tr><td>Curve</td><td></td></tr><tr><td>Line</td><td></td></tr><tr><td>LinearFit</td><td></td></tr><tr><td>Spline</td><td></td></tr></tbody></table>

Goldberg (1983) and Pinson and Wiener (1988) as well as the code and examples in the system browser of the ST-80 (Version 2.5) system.

## Class Hierarchy for DisplayObjects

Table 7.4 displays a simplified version of the class hierarchy for **DisplayObjects**. The superclass of the objects is **DisplayObject** which contains most of the abstract protocol for many objects that can be displayed on the screen.

Table 7.5 provides more detail about the classes shown in the hierarchy displayed in Table 7.4 and adds additional classes that permit drawing on the screen such as the class **Pen**. The subdivision into three segments shown in Table 7.5 is similar to the segmentation in the ST-80 browser. The first category contains primitive display objects of simple drawing elements, the second category contains often-used display objects, and the third category provides brief definitions for several display objects based on paths. The reader should note that these graphics constructs are only available for backward compatibility in ST-80, Release 4 and higher versions.

## Displaying Objects

Displaying objects on the screen is very simple. Forms are created as bitmaps, that is, simple rows of 1's and 0's. Forms are the ST-80, Version 2.5, equivalent of Release 4 images with a depth of 1 bit. The Smalltalk (ST-80)
<table><caption>**Table 7.5** Commonly Used DisplayObjects in Version 2.5</caption><thead><tr><th>Name</th><th>Utility</th></tr></thead><tbody><tr><td><strong>Primitive DisplayObjects</strong></td><td></td></tr><tr><td>Pen, point, quadrangle, rectangle</td><td>Drawing lines, graphs, rectangles / quadrangles (rectangles with an inside color)</td></tr><tr><td><strong>Common DisplayObjects</strong></td><td></td></tr><tr><td>Cursor</td><td>Pointer representation</td></tr><tr><td>DisplayMedium</td><td>Abstract class for form and cursor</td></tr><tr><td>DisplayObject</td><td>Protocol for most displayed objects</td></tr><tr><td>DisplayScreen</td><td>The computer screen</td></tr><tr><td>DisplayText</td><td>Text for display</td></tr><tr><td>Form</td><td>A bitmap</td></tr><tr><td>InfiniteForm</td><td>An unbounded form</td></tr><tr><td>OpaqueForm</td><td>Parts of the bitmap are opaque and parts are transparent</td></tr><tr><td>Paragraph</td><td>Text for editing</td></tr><tr><td><strong>Path DisplayObjects</strong></td><td></td></tr><tr><td>Arc</td><td>A quarter of a circle</td></tr><tr><td>Circle</td><td>Four arcs</td></tr><tr><td>Curve</td><td>A conic section determined by three points</td></tr><tr><td>Line</td><td>Straight line</td></tr><tr><td>LinearFit</td><td>Piecewise linear approximation</td></tr></tbody></table>

screen with 1's and 0's representing forms can, of course, display only black and white. To display near white and near black as well as shades in between using the form model, it was necessary to display varying numbers of black-and-white dots in an area.

## Forms

In Version 2.5, **Form** was likely to be one of the most important classes that the beginner would first learn to display on the screen. The display screen of the computer is a global variable called "Display." It was straightforward to display a form anywhere on the screen; for example,

`aForm displayAt: 0@0`

would place "aForm" at the upper right-hand corner of the screen. In this example, "aForm" is any instance of a form created by using the form editor or
obtained from other sources (e.g., a scanned image). The most direct way to test
this code is to grab a form from the screen and display it. For example, one
could enter the following code in a workspace, highlight the code, and select
“doit” from the operate menu:

|aForm|
aForm := Form new fromUser
aForm displayAt: 0@0

This example is essentially the same as the example given in a previous example
using images. However, note that with forms, the image could be displayed
anywhere on the screen. In the newer versions of ST-80, the display surfaces are
limited to host windows.

Figure 7.5 shows a way to display large forms, called canvases (see the
Appendix concerning the class that implements a canvas). A canvas permits
having a constrained size viewport that can seemingly be moved around the
entire form by grabbing the scroll bars (i.e., positioning by using the cursor) to
move the canvas. The methodology used is simple, because a form is composed
of bits. Whenever a scroll bar is moved by use of the cursor, bits are copied in
the direction that the scroll bar is moved, thus creating the illusion of panning
the viewport over the form. The code for implementing this class is available as

<figure><img src="image_75.png" /><figcaption>**Figure 7.5** Displaying a Canvas.</figcaption></figure>
indicated in the Appendix (both Version 2.5 code and Release 4 code is
available).

## Pen

A concept found in most early versions of Smalltalk is the pen. This idea has disappeared from Release 4. The intellectual basis for using a "pen" for drawing came originally from the Logo language (Papert, 1980). A line drawing method that used a turtle was invented for teaching children about programming ideas. Children could relate drawing to a physical turtle holding a pen that could be moved up and down. In fact, robot "turtles" with pens, that is, mobile robots with drawing instruments, were created as an output facility for teaching programming in Logo, a language very much like Lisp. The turtles were given such commands as "Pen up," "Pen down," north, and so on, that is, easy to understand commands sent to move the turtle and the pen. In Smalltalk, Version 2.5 and earlier, the pen was operated by creating a new pen instance, for example, *aPen* := *Pen new*. The pen instance can then be moved up or down (off the paper or touching the paper), turn, go a distance, go to a location, and so on. This methodology makes it extremely simple to produce line drawings. The pen nib can be any shape, including different forms.

A demonstration of the use of the pen is shown in Figure 7.6, which shows how a pen can be used to make a freehand drawing on the display. This example shows both the code and an example of having a pen follow the cursor as it is moved on the screen. In the figure, "bic" is defined as an instance variable that is assigned to the new pen instance. First, the pen is raised and moved to the location where drawing should begin and the pen lowered. Then, as long as no mouse button is pressed, the pen follows the location of the cursor. *Sensor mousePoint* returns the current location of the cursor. Compare this methodology for drawing to the examples presented using *displayLineFrom/to*: given in the previous section using the drawing method available in Release 4. One should note that there is little difference between the two techniques.

## Paths

The class **Path** in pre-Release 4 ST-80 versions permitted specification of paths on the screen which could be used to display forms. For example, lines, arcs, circles, and most other kinds of figures could be displayed by creating a path. An instance of the class **Path** contained a collection of points. For example, consider Figure 7.7 which shows a very simple example of creating a
<figure><img src="image_76.png" /><figcaption>Figure 7.6 Drawing with an Instance of Class Pen (Version 2.5).</figcaption></figure>

<figure><img src="image_77.png" /><figcaption>Figure 7.7 An Example of Creating a Line with Class Path (Version 2.5).</figcaption></figure>
straight line. First, the local variable "path" is assigned to an instance of the class **Path**. The form used for drawing is assigned and the points to be employed are generated using the "do:" and finally the path is displayed on the display. In the iteration, the loop generated 40 points, each of which added a specific screen coordinate to the collection stored in the instance of **Path**. Each point has the form x@y; for the case shown, the points were generated from 301@301 to 340@340. Because the screen on which this example was generated had its top left corner as the origin (i.e., 0@0), the line was drawn from top left to bottom right as shown.

Generation of a path is a useful technique for animation in simulation applications. Imagine that a form is drawn on the display upon which an object should move to simulate some situation, for example, traffic moving on a grid of streets. The background grid could be generated as a form and shown on the display. Small forms to display automobiles could be created as forms or opaque forms which could be displayed on the background form and moved along a preset path to give the appearance of animation. The same technique could be employed to simulate customers moving in a bank, ships moving from point to point on a map, and so on.

Paths have disappeared from Version 2.5 in favor of using displayPolyLines with a collection of points. Moving small images to create simulations is easily accomplished in Release 4 by having images follow a collection of points.

## Animation

Animation required movement of forms or pens in Version 2.5. Pens could be used to dynamically draw pictures or sets of pens could be driven together to create the appearance of drawing simultaneity. By capturing where a pen draws and the size of the nib, a line drawn by a pen could be erased by drawing a white form over the path of the black line. This technique works fine for drawing and erasing a pen on a white background. However, if the background is not white, the background needs to be saved. Forms when moved over another form should save and restore the background (see method 'background: at:' in class DisplayObject) unless the background is white. This idea also holds for animation using images in Release 4.

## 7.5 Windows and Views (Release 4)

### Concepts

A window forms the rectangle around either single or multiple views, including the border. Views are contained inside a window. When multiple
<figure><img src="image_78.png" /><figcaption>**Figure 7.8 Methodology for Specification of CompositeParts within a Window.**</figcaption></figure>

views are shown within one window, wrapped views are packaged as a collection of parts, contained within an instance of class **CompositePart**. Each view interior to a window can be considered to be a composite part of the window. In some systems, multiple views existing within a window are known as "panes" (e.g., Smalltalk/V) by analogy to windowpanes. In Smalltalk-80, the class **View** is used as an abstract for other view-related classes such as **ListView**, which implements the functionality for selecting items within a list. Functionality for moving, collapsing, and resizing windows is relegated to the host windowing system. Normally, several views are created in an application window. Resizing a window can automatically resize the attendant views implemented as composite parts of the window. Figure 7.8 presents an example of one method for specifying views as fractional parts of a window. The entire window is defined to have an extent of 1, that is, 0@0 to 1@1. Each view is defined as a fraction of the window to which it belongs so that when the window is resized, all the composite parts of the window can be proportionately resized as well.

## View Operations

Table 7.6 shows examples of some of the subclasses of **View**. **Boolean-WidgetView** provides basic functionality for things that turn on and off. **Display-**
<table><caption>**Table 7.6** Basic View Types in Objectworks \ Smalltalk-80 (Release 4)*</caption><tr><td>View</td></tr><tr><td>BooleanWidgetView</td></tr><tr><td>LabeledBooleanView</td></tr><tr><td>DisplayTextView</td></tr><tr><td>FractionalWidgetView</td></tr><tr><td>LauncherView</td></tr><tr><td>ScrollingView</td></tr><tr><td>ScrollingLinesView</td></tr><tr><td>StringHolderView</td></tr><tr><td>TextView</td></tr><tr><td>ListView</td></tr></table>

**TextView** is a class for displaying text. The **LauncherView** provides a way to display an initial menu that is present on the screen when Smalltalk is launched that can be used for running applications and system tools. **ScrollingView** and its subclasses for **Text** as well as **ListViews** provide basic functionality for text and lists. All the different view types have different pop-up menu functionality associated with the controllers that are used for operating the view. Most views, however, have a common type of operation for sizing, moving, and restoring windows. For example, Figure 7.9 shows two versions of the pop-up menu associated with the operate button on the mouse for resizing, restoring, and moving a window. Note that the appearance of the menus is somewhat different for different Smalltalk versions but has essentially the same functionality. **ScheduledWindow** is a class that is used to secure a new window from the host operating system. This class provides window functionality including sizing, coloring, and opening new windows. Many methods are available that can be examined using the system browser. A simple example will illustrate how straightforward it is to create a new window on the screen:

```perl
[aWindow]
aWindow := ScheduledWindow new.
aWindow label: 'Example Window';
minimumSize: 300@200;
insideColor: ColorValue blue;
open.
```

By highlighting this code in a workspace and selecting "doit" from the operation menu, a new window will appear on the screen with the label shown and a blue interior color. The window that is opened can also be closed by simply sending

<footnote>*Abstracted from ST-80 class information, ParcPlace Systems, 1990.</footnote>
<figure><img src="image_79.png" /></figure>

<figure><img src="image_80.png" /><figcaption>Figure 7.9 Operate Pop-up Menu for Two Different Platforms.</figcaption></figure>
close to the window. For example, one can create a new window in a workspace and open it:

Awindow := ScheduledWindow new.
Awindow open.

and then close the window by

Awindow close.

In this example, the window will have a minimum size. The global variable "Awindow" was used simply to make it easy to access the variable from a workspace. In actual programs, the variable bound to the new window would probably be contained in a class instance variable.

## Displaying in Views

Normally to display views of text, lists, images, and so forth, views of a particular type (e.g., `SelectionInListView`, `DisplayTextView`, `BooleanWidgetView`, etc.) are created and added at a particular location in the container of views that fill a window. Each particular type of view will have its own capabilities, including different types of scrolling. For example, a list may scroll only up and down, but a canvas<fnref n="1" /> will have scroll bars to scroll in two directions. Images can be created and displayed in any view.

A particularly interesting issue is the use of nonstandard views to add meaning to the display. For example, an electronic circuit might be represented as a collection of many views, each of which could be represented as an icon that has a visual identity corresponding to its physical reality (e.g., symbols for transistors and resistors). Each view might be collapsed and when expanded could show more information about the internals of the component or subcircuit that is expanded. This idea is particularly useful for representing whole-part hierarchical relationships. The alternative to this representation scheme is to place images on a background which represent the subparts of the thing being displayed. For example, for this electronic circuit, images of resistors, transistors, and so on would be positioned at various locations on an image and information about the size and extent of the positioned images would be maintained in a dictionary. The trade-off between these two alternatives is capability and speed. The first methodology gives a large capability for ease of

<footnote n="1">¹See the Appendix.</footnote>
manipulating hierarchical representations, such as designs, but pays a penalty in speed for having to maintain many view relationships in a hierarchy. In contrast, the image-based methodology is much faster, simply having to display images at various locations on the screen.

## 7.6 Basic Direct-Manipulation Interface Design Elements

### General Issues

This section examines the specific kinds of views that can be built into an application. Information about styles and the look and feel will be given here; Chapter 8 will examine specific code-related issues. The elements used in designing a user interface should, first, be open and observable. The user should be able to either intuitively understand how to use the interface or with some training understand how the system designer intended the system to be used. This latter point is relevant to the ST-80 system. It is not immediately intuitive to the novice user how to operate ST-80, because learning to operate the mouse and understanding how and when menus pop up are prerequisites to operation. A completely intuitive interface would not require such information to be learned prior to operation. For example, displaying buttons that say "Press me" would be intelligible to users who understand basic mouse operations. However, even systems with this style would fail with a novice who presses the screen with his or her finger! Hence, the first point in building an interface is that it is essential to evaluate what skills prospective users will have and evaluate how to provide users who have inadequate skills with the necessary instruction to be able to operate the system.

To build an application, the screen layout should be considered, particularly how much information can be shown on the screen at once. Having the capability of providing both tiled and overlapping windows, an assessment should be made of the complexity of tiled windows for parts of the application along with an evaluation of how often a user would need to switch between overlapping windows. Of course, overlapping windows is not a problem when the physical screen is large. It is an issue, however, when small screen sizes are employed, such as on certain Macintosh or PC screens. Views should be uncluttered; however, there is a considerable temptation to design cluttered interfaces that provide the user large amounts of information. One solution is to design a continuously visible control panel that directs the operation of the application, moving from one tiled window to another as the user proceeds through the application. Use of menus is another design issue; pop-up and pull-down menus provide the most clutter-free design but also do not yield
<figure><img src="image_81.png" /></figure>

<figure><img src="image_82.png" /></figure>

<figure><img src="image_83.png" /><figcaption>Figure 7.10 Three Types of Menus: Hierarchical, List, and Pull-Down. [Reprinted with permission of Knowledge Systems Corporation.]</figcaption></figure>
much observability of the available operations in an application. One technique to solve this problem is to mix control by providing both switches and menus; in some cases, it may be useful to pop up a menu when a button is pressed!

## Menus and Lists

Listing of items from which selections can be made is a typical component of user interfaces. Figure 7.10 shows several styles of menus: a simple list, a list that uses different font styles, a pull-down menu, and a hierarchical menu. Lists can be either fixed in a view and scrollable, pop-up, or pull-down. Both of the latter can be scrollable as well. The hierarchical menu probably provides the highest degree of information for the least space used. The hierarchical menu in Figure 7.10 shows how the system menu can be reimplemented using hierarchies rather than using the LauncherView (compare with the Launcher in Figure 6.1). Figure 7.11 illustrates the ease with which a hierarchical menu can be built using the ST-80 hierarchical menu building facilities. This figure shows both the code and the result of running the code. Note also in this example that the menu selection is bound to a variable called

<figure><img src="image_84.png" /><figcaption>Figure 7.11 Implementing a Hierarchical Menu.</figcaption></figure>
<figure><img src="image_85.png" /><figcaption>Figure 7.12 Examples of Four Different Styles of Buttons.</figcaption></figure>

"selection." When a selection is made, the selection is bound to the variable of the same name, in this case. The last line of the code in the figure illustrates the use of this information to perform some task associated with making the selection. Sending self "perform: selection" will cause a method called selection to run within "self," where "self" might be the current class or class instance.

## Buttons

Figure 7.12 shows four examples of different kinds of buttons. On the left of the figure are radio buttons. Pressing one button turns the others off. An example of switches are shown on the top right. Switches require successive mouse clicks to turn a switch on and off. The box and the label reverse color as the switch alternates between on and off. The toggle switch toggles between alternatives. Also shown are two icons, a hand and a symbol for writing, that are part of the ST-80 system. Icons can also be used as pictures on buttons.

## Icons

Figure 7.13 shows the concept of the use of icons. An icon is simply a miniaturized symbol for an operation. There might be, for example, a set of icons that represent the collapsed views of things such as browsers, text editors, and other common elements in the GDMI environment. Or, icons could be used to graphically represent the actions of various buttons on a view. Any-
<figure><img src="image_86.png" /><figcaption>**Figure 7.13** Using Icons to Represent Windows.</figcaption></figure>

where that an image can be used in association with an item that is directly manipulatable, there is the opportunity to use an icon. The default behavior for icons is to write text on a small rectangle representing a collapsed view. Whether an image that has the appearance of a door, for example, or a rectangle that has a label on it is more or less understandable to the user is open to question. Proponents of icon utilization argue that these types of graphic images promote system understanding; opponents likewise argue that there is little value added. The answer is perhaps that icons should be used if there is a clear need in the application to mimic something in the real world that would make common sense and thus make the operation transfer task more clear to the user. Otherwise, text will work fine.

## Text and Code Presentation

Text is easily entered and displayed using the **TextEditor** class. Figure 7.14 shows an example of using different font styles for different parts of typed text. Text can be collected and automatically formatted to the size of the workspace. Font and style selection is via the operate-button pop-up menu. Text presentation is very useful for communicating with the user. A typical use is the system transcript which provides messages from the system such as error messages. This same type of transcript can be employed by the user for special text communications as shown in Figure 7.15. This figure shows the creation of a TextCollector view called "Announcer" which can be sent a message from
<figure><img src="image_87.png" /><figcaption>Figure 7.14 The Use of Different Fonts in Text.</figcaption></figure>

anywhere in the system. The result of sending a string is shown in the demonstration window in this figure.

Typing Smalltalk code into a CodeView provides the capabilities of organizing text, for example, for building methods. In the system browser various text-handling capabilities are built in including the "format" command which provides a "pretty printing" capability for ST-80 code; that is, when "format" is selected, the code in the view will be parsed and reformatted

<figure><img src="image_88.png" /><figcaption>Figure 7.15 Creating a Global Text Collector.</figcaption></figure>
according to formatting rules. Often, this provides more readable code. Note, however, the user must still "accept" the code, that is, compile the code and register it in the browser.

## Using the Keyboard

In some cases, it may be easier to use the keyboard than the mouse for accomplishing various operations. In various word processors, it is common practice to permit a user to employ the mouse or to capture various operations using function keys or combinations of keystrokes on the keyboard. In ST-80, several examples exist that map mouse operations onto the keyboard. One specific example of the use of the keyboard is for adding text characteristics to text in a text window. Key combinations for underlining, adding bold, changing serif, and so on, are available via a keystroke combination. For example, the combination <esc>-b will add boldness to the highlighted text selection. Whether or not such operations are better accomplished by the use of the keyboard or by the mouse appears to be completely driven by user preference.

## Mousing

Novice users of a mouse can learn mouse operation quite quickly—pointing and clicking comes naturally to users. However, becoming facile with the mouse requires more extensive use. A common experience is that users who consistently use the mouse become faster and faster with operations over time, as expected. Text editing using the cut, paste, and copy operations between multiple windows and the use of intermediate workspaces for editing text, making notes, and editing images can eventually be coordinated by rapid mouse operations. Perhaps the greatest advantages for using a mouse are that mouse-style operations: (1) implement the point-and-click metaphor, thus reducing ambiguity about operations, (2) open computer systems to persons with little typing capability, and (3) assist in focusing a user's attention, for example, by activating a window when the mouse is moved inside the window.

## 7.7 Graphically Tailoring the User View

The next few paragraphs discuss options that the programmer has for creating a user interface. Both the capabilities of the standard interface and ways to extend the standard interface are discussed.
## Capabilities of the Standard ST-80 User Interface

As discussed previously, there are a variety of tools that are available in the standard ST-80 user interface that permit creating user interfaces with standard features such as lists, menus, buttons, text windows, and images. These features, when combined into a window and coupled in a model-view-controller relationship, allow creation of various relatively complex user interfaces that are suitable for many applications. Even these relatively simple interface concepts can be easily tailored to provide more distinctive interfaces. For example, icons and buttons can employ user-created images to provide a more visual reminder of functionality. Views can be rearranged to be different from the standard "paned" or " tiled" views discussed. For example, there is no reason that views cannot be scattered around a window such that the views take on meaning by how they are represented. In a standard "paned" or " tiled" view, there are few hints about the intended functionality of the view, other than recognizing what is implemented in the view (e.g., a list, a button). As discussed previously, a view of a flowchart or a view of electronic components could permit the user to understand the use of the views within a larger context. For example, imagine that each block in a flowchart or each component in a schematic is a separate view. Because each view can have its own functionality apart from its organizing container in the window, these example views could permit viewing of their contents or present other relevant information. The point of this discussion is that there are many ways to tailor the user interface without making major changes to the standard components that are available.

## Custom Interfaces

It is a relatively short step from using the standard ST-80 components to more complex user interfaces. Next, a number of ideas about enhanced user interfaces are discussed.

The Alternate Realities Kit (ARK; Smith, 1987) extends the ST-80 environment in several ways. The objective of Smith's work was to create an environment in which the influence of physical laws could be observed (e.g., on a planet moving around the sun) and to be able to change laws and see the effects of the change on the alternate reality created. Smith addresses the issue of literalism and "magic" in a user interface. Literalism simply means that the actions that occur are literally what the user would expect; for example, pressing a button marked exit causes that action to occur. The term "magic" comes from adding capabilities to an interface that are not so literally understood. For example, Smith added the capability of dragging buttons to an object which could be used to operate the object in different ways. If the object did not
<figure><img src="image_89.png" /><figcaption>**Figure 7.16** The Alternate Reality Kit Concept (explaining concepts in Smith, 1987).</figcaption></figure>

understand the messages from the button to the object, then the button could not be attached to the object and would drop through it—"magic"! Figure 7.16 shows how the ARK environment is extended from ST-80. An ST-80-style interface is shown on the bottom layer of the figure with an image and a switch on the image. The mouse cursor is shown pointing to the switch. The top layer shows how the ARK user interface modifies the capability of the ST-80 environment to provide a slightly different display. Instead of a simple cursor, a moveable image showing a hand is displayed and buttons can be moved on top of an object. If the button is accepted on the object, then the hand can press the button to achieve a desired action, for example, a simulation. This type of interface is perhaps somewhat closer to reality and has some aspects that make it easier to use than the standard ST-80 environment.

An interesting type of interface is one that assists in organizing knowledge according to commonsense spatial organizations that are easily remembered. For example, Figure 7.17 shows a drawing of an interface that is configured to look like a room in a library. All the objects in the room can interact with the mouse, and actions are accomplished by clicking the mouse button while pointing the cursor at objects in the room. For example, the novice user will probably inspect the magazine on the table in the middle of the room marked "read me" when first using the system. Likewise, there are books on the bookshelves with labels and pictures on the walls that will give more information when accessed. A door to the right opens to other rooms with "more" information. Admittedly, this representation is attractive to the naive user—but is it useful to the accomplished user? The answer is probably not! The
<figure><img src="image_90.png" /><figcaption>**Figure 7.17** The Room Metaphor as a User Interface.</figcaption></figure>

accomplished user learns to organize information and how to operate a system and thus does not need the visual cues afforded in this graphics user interface. For the novice user, the cue "read me" on the table is a useful one; yet, the same cue could be presented in a box on the screen that would serve perhaps equally well in a less elaborate interface setting.

Another type of interface is shown in Figure 7.18 patterned after the user interface style of RMG, a simulation system from Hewlett-Packard, (RMG, 1989). In this figure, commands are arrayed around the periphery of the view and moving of the view is controlled from the sliders on the right of the figure. In this example, a view of a molecule, the molecule is moving and zooming in and out is permitted. The idea of animation controlled from the buttons around the view is an interesting presentation interface.

Simulation environments can be readily created to enhance the standard features of Smalltalk. Consider the manufacturing floor plan in Figure 7.19 which shows how an electronic circuit board is created by passing the board from one machine to another along a flexible manufacturing line. This example utilizes only standard Smalltalk graphics features. The line appearing as a U shape is represented as an image with small images located at strategic locations on the image. For example, the blocks marked "k" are baskets for placing a completed unit; as a unit is manufactured and passed from one machine to another, the boxes "k" fill and empty as the board passes along. The only movement is the circuit board which can be demonstrated graphically to the
<figure><img src="image_91.png" /><figcaption>**Figure 7.18** The RMG User Interface. [After RMG (1989); reprinted with permission.]</figcaption></figure>

user by sequentially turning the “k” boxes black and then white. This gives the illusion of movement. The remainder of most of the features on this diagram are simply standard Smalltalk features, arrayed in different ways. One additional feature, is the use of Pluggable Gauges (Adams, 1987)<fnref n="2" /> which are variable gauges that can show information about several items. In this example, gauges are used to show the percentage of team utilization, the simulation speed, the duration of the simulation, and the percentage of utilization of each machine. Chapter 14 will expand this example.

Finally, a useful addition to the types of user interfaces discussed previously is the addition of video to the presentation capabilities of the user interface. Figure 7.20 shows a schematic diagram of how to mix video and an application view. The support for this composite is the addition of a video controller which permits merging of video and a standard screen presentation. Video, supplied from various sources, such as a video disc player or camera, can be controlled by the computer (e.g., by using a serial connection to start or stop the disc player). Using a system of this type, the mixing of video and standard presentation interfaces permits presentation of animated clips of information as well as presentation of many still pictures.

<footnote n="2">²Some gauges for use in Release 4 are available to readers of this book, as indicated in the Appendix.</footnote>
<figure><img src="image_92.png" /><figcaption>**Figure 7.19** An Example of a User Interface for Manufacturing. [Dehner (1990); reprinted with permission.]</figcaption></figure>
<figure><img src="image_93.png" /><figcaption>**Figure 7.20** Adding a Video Interface to a GDMI.</figcaption></figure>

**References**

Adams, S. (1987). *PluggableGauges*. Knowledge Systems Corporation, Cary, NC.

Dehner (1990). Class Project, EE396, Vanderbilt University, Spring Semester, 1990.

Goldberg, Adele (1983). *Smalltalk-80, The Interactive Programming Environment*. Addison-Wesley, Reading, MA.

Holzgang, D. A. (1988). *Understanding PostScript*. Sybex, Inc., Alameda, CA.

Hutchins, Hollan, J., and D. A. Norman (1986). Direct Manipulation Interfaces. In *User Centered System Design, New Perspectives on Human-Computer Interaction*, D. A. Norman and S. W. Draper (Eds.). Lawrence Erlbaum Associates, Hillsdale, NJ.
LaLonde, W., and J. Pugh (1989). Film Loops and Animation. *Journal of Object-Oriented Programming*, Vol. 1, No. 5, January/February, 64-72.

Papert, Seymour (1980). *Mindstorms: Children, Computers, and Powerful Ideas*. Basic Books, New York.

Pinson, Lewis J., and Richard S. Wiener (1988). *An Introduction to Object-Oriented Programming and Smalltalk*. Addison-Wesley, Reading, MA.

RMG, A Tool Kit for Development of Visualization Courseware (1989).
Hewlett-Packard, Cupertino, CA.

Schiefler, R. W., J. Gettys, and R. Newman (1989). *X Window Systems: C Library and Protocol Reference*. Digital Press, Maynard, MA.
Shneiderman, B. (1982). The Future of Interactive Systems and the Emergence of Direct Manipulation. *Behavior and Information Technology*, Vol. 1, 237-256.

Shneiderman, B. (1983). Direct Manipulation: A Step Beyond Programming Languages. *IEEE Computer*, Vol. 16, No. 8, 57-69.

Smith, Randall B. (1987). Experiences with the Alternate Reality Kit: An Example of the Tension between Literalism and Magic. *IEEE Computer Graphics and Applications*, September, 42-50.

## Exercises

7.1 Make a detailed list of command line interface commands that you frequently use. Now, create on paper a user interface using direct-manipulation principles that provide the same functionality. Are there any problems in providing the same functionality with a direct-manipulation interface?

7.2 Describe how copying files can be accomplished in a direct-manipulation interface.

7.3 There has been considerable research conducted with the objective of giving machines the capability for natural-language understanding. Compare an interface that can understand plain English to a graphics interface. Which types of applications would be most useful for both types of interfaces? Consider aspects such as response time, user capabilities (e.g., typing skills), and appropriateness.

7.4 As mentioned in the chapter, there are many different kinds of pointing devices that have been used. Consider and compare the use
of a mouse to the use of a touch screen. Imagine that moving your
finger around on the surface of the computer screen would permit you
to conduct the same operations as you conduct with the mouse. Would
you prefer this type of interface?

7.5 Investigate images further. Try to display images on the screen at various locations. Write a routine that will permit an image to follow the cursor around the screen. One can detect the location of the cursor with *WindowSensor cursorPoint*. Use the **VisualComponent** method *follow:while:on*: and display the result in the workspace you use for the test code, or in a workspace you generate yourself. (*Hint*: Proceed in the same way as the example for displaying images and use the previously mentioned animation method.)

7.6 Suppose you were going to write a simulation of customers moving in a bank. Draw a sketch of how the bank would look on the screen and write the code needed along which customers would move in the simulation.

7.7 Look up the referenced article by Smith on ARK. Read and review the article and consider what other types of user interface mechanisms might be used.
<figure><img src="image_94.png" /></figure>
# Tools for Building Applications: The Model-View-Controller Paradigm and View Components

## 8.1 Model-View-Controller Concepts

This chapter describes the major interface tool available to the user for building applications in Smalltalk-80—the model-view-controller (MVC). The initial design concept for creating the model-view-controller (Krasner and Pope, 1988) was the factoring of conceptual entities when building applications. Typically, it is easy to understand how to break down the components of an application into three easily recognizable parts: the *model*, that part of the application that deals with the information to be utilized; the *view*, the presentation of the application on the display screen; and the *controller*, the code that controls the interaction of the system with the user. Example code contained in this chapter was created with Release 4 of ST-80.

### The Basic MVC Concept

Figure 8.1 provides a conceptual framework for organizing a description of the MVC. As discussed in Chapter 7, the user is linked to computer system input via the mouse and keyboard and output is conveyed via the computer screen. The task of the controller is to interpret input from the user, track the mouse movements, and handle interactions with views and models. The model houses information, for example, collections of data points, images, or rules, whereas the view deals with information displayed in windows on the screen. This three-way factoring is used for building most applications in ST-80. Each view may be displayed in a window on the screen either by itself or as one
<figure><img src="image_95.png" /><figcaption>**Figure 8.1** A Conceptual Framework for the Model-View-Controller. Dark hatched arrows are messages between MVC components. The broad hatched arrow is an update message from the model to the view. Nonhatched arrows indicate connectivity between the user and the MVC.</figcaption></figure>

of several views arranged within a window. Views and controllers are directly linked and may directly access information about each other. Models, however, are more isolated from views, yet can indirectly inform views that the information they contain should be displayed. Models may be linked to many different view/controller pairs so that information can be displayed in different ways. The central idea is that the model maintains a collection of dependents, that is, things that are dependent on it. There can be different types of dependencies; for example, in a class for a push button, pushing any button will cause any other dependent button that is "on" to turn "off" (i.e., the buttons on a car radio). Similarly, there may be several views that are changed in some way when information in a model is changed.

As an example, consider a model that is simply a collection of data points, implemented perhaps as simply as an object with an instance variable initialized to a new orderedCollection of length 1024. Two views on the screen might be implemented, one to show the raw data and one to display the fast Fourier transform of the data, for example. If a user changes the data in the model by sampling additional points, then presumably both the plot of the original data on the screen and the FFT of the data would need to be changed. This updating of information on the screen is accomplished by creating a collection of dependents of the model—in this example, the two different views of the data. Whenever data changes, the dependent views should be automati-
cally changed, as well. This concept can be extended indefinitely to create as many dependents as needed to display different views on the screen.

## Models

Model is a subclass of Object, adding the instance variable "dependents." The collection "dependents" holds all the dependents of a model that the user specifies. These dependencies are created when an application is initially opened. Whenever information in the model is changed that can affect the view, the user can supply code of the form:

self changed

or

self changed: aSymbol.

or

self changed: aSymbol with: aParameter.

in any method in the model. Any of these methods results in an *update* message being sent to the view that is linked to the model. The typical method writing approach for the model is to write all the methods that implement the model and to include *changed* messages whenever what is to be shown in the view should be redisplayed. The final *changed* message listed previously is ultimately sent as a consequence of sending either of the first two messages. Sending any *changed* message results in the sending of an *update:with:from:* message to the *dependents* of the model. The argument in the "from:" part of this message can be used to indicate from which object the change comes. The utility of passing the argument "aSymbol" to a view is to permit selective updating of the visual information displayed in the view. The view should detect what changes are to be made by examining "aSymbol" and then taking an appropriate action. The dominant use of "aSymbol" is to permit differentiation among multiple views displayed. For example, imagine that an application has several different views. Whenever a change in some part of the model that is relevant to one or more
views is made, an aspect symbol can be specified in the view that, when detected, permits the view or views to be selectively updated.

## Views

Each view has just one controller; yet multiple view/controller pairs can be linked to a single model. When an *update* message is received by a view from a model, the "update" method in the view should call `displayOn: aGraph-icsContext` method to change the visual appearance of the view. Users should implement the `displayOn: aGraphicsContext` method in each view displayed. Because there may be only selected views or parts of a view in a window that need to be redisplayed when the model is updated, redisplaying everything in the entire window is often unnecessary. As an example, consider a simulation which requires the display of a small image at various locations on a larger image. A traffic simulation is an example in which a small image depicting an automobile is displayed on an exit ramp. If the model contains the information about where the car is to be located, then each time the model changes, the image representing the car should be moved to a new location on the back- ground image, which does not change. Rather than redisplaying the entire image at each update, it would be useful to implement code in the *displayOn*: method of the application view that simply saves and restores the background behind the image displaying the automobile and moves the small automobile image. The time savings comes from only having to manipulate a small part of the display rather than the entire background. Another simple example would be for the display of gauges; when a value is changed, only the indicator part of a gauge needs to be redisplayed. In summary, the *'changed: aSymbol'* → *'update: aSymbol'* messages permit selective updating of a view. The model can indicate that only some aspect of the model (denoted by aSymbol) has changed. By passing this information to the view, via *update: aSymbol*, one can cause the view to selectively update itself.

## Controllers

Controllers coordinate models and views with user input. There is little inherent behavior in class **Controller**, except for sensing whether the cursor is inside a view and whether the mouse buttons are pressed. **Controller-WithMenu** adds the capability of associating menus with mouse buttons. The default behavior of the controller is to initialize, enter a control loop, and finally terminate. Figure 4.6 described some of this behavior. Subclasses of controllers
can implement many different types of behaviors. For example, different types of menus can be specified, various actions can be taken when buttons are pressed or released, text editing control can be specified, and list control can be provided. Control regimes that are not common can be implemented, as well. For example, when a view appears on the screen, the cursor could be displayed as a helpful graphic symbol positioned at a predetermined point that helps the user understand what to do next. Also, subclasses of controllers could be implemented that would track the cursor and record what the user is doing. This capability would be useful in tracking the characteristics of the user so that the system could adapt its presentation format to the needs of the user.

## Windows

The class **ScheduledWindow** provides the interface to the host window manager system. The capabilities of the window manager are specific to each host platform; hence, the visual appearance of the window will vary between platforms, even though the code is completely portable among platforms. Views live within the host window and are installed in specified areas of the window. Each view requires a *wrapper*, or set of code that implements different view functionality. For example, views can be wrapped to have borders (**BorderedWrapper**) and scroll and menu bars (**EdgeWidgetWrapper**). The capability of permitting applications to move from one host platform to another, adopting the interface look and feel of each new host platform, is a particularly appealing feature of ST-80.

Next, three methodologies for building MVC triads are discussed in general, followed by a description of view components. Then, concrete examples of each of the three methodologies will be presented.

## The Build-It-Yourself Method

The most direct, yet most tedious, technique for building MVC triads is to write the code yourself for specifying the characteristics of the linkages between views, controllers, and models. The alternative is to utilize some type of more automated technique, two of which will be described in the following discussion. The technique utilized for building a MVC triad yourself is to specify all the relationships in the triad, as well as information about the window within which the triad lives.
The first job is to specify the window, normally in the "open" or "openOn:" class method, which can exist in the view or model. For example,

open

<table><tr><td>"ClassName open"</td><td>"temporary variables for this"</td></tr><tr><td>|window compositeParts|</td><td>"method"</td></tr><tr><td>window := ScheduledWindow new.</td><td>"the new message creates a new"</td></tr><tr><td>compositeParts := CompositePart new.</td><td>"instance"</td></tr><tr><td></td><td>"create a place to hold the views"</td></tr></table>

"... next add the views to different composite parts..."

<table><tr><td>window component:</td><td>"associate the parts with the"</td></tr><tr><td>compositeParts.</td><td>"window"</td></tr><tr><td>window open</td><td>"open the window"</td></tr></table>

Typically, to create an instance of a view and install the view as a composite part, both the model and controller are specified. For example, prior to opening the window in the preceding example, the view should be created and added to the compositePart description.

```
drawingView := DrawingView new
    model: aDrawingModel;
    controller: aDrawingController new.
```

```
compositePart add: drawingView borderedIn: (0@0 extent: 0.3@0.1).
```

In this example, drawingView is an instance of a particular class of the same name (note that the capital letter distinguishes the two). By sending *model*: *aDrawingModel* to the view, the model to view linkage can be established. In the same way, the view to controller link is directly specified. For each view that is to be displayed in only a portion of a window, it is necessary to tell the window where the view will be displayed, as indicated previously. In this example, the drawingView will be shown with a border in a small area in the top left of the window (as indicated by the argument to *borderedIn*).

The preceding example, which will be amplified in some detail in the following discussion, shows only one of the techniques in which the controller and model of a particular instance of a view are explicitly set up by sending the methods *model:* and *controller:* to an instance of a view. There are other
techniques as well; for example, in most cases a default controller can be used. Most view classes have prespecified controllers which are included if the user does not specify a new controller class.

## The PluggableView Method

In the ST-80 system, there are several examples of so-called "pluggable views." Pluggable views simplify building user interfaces by permitting the builder of an application to create instances of a variety of specific kinds of views for an application simply by passing parameters (i.e., "plugging parameters in") to the view class. Several of these pluggable views will be explained in the following discussion.

## ViewBuilder Methodology

The third technique for building views, including basic models and controllers, is to use a graphics interface which permits graphically sizing and distributing different types of views on a graphic prototype of a new window being built. The technique requires no programming knowledge. A user can create a new view by sizing a window on the screen and can add various pluggable view components just by selecting items from a list. This methodology is the simplest of the three techniques described; one drawback, however, is that because no knowledge of Smalltalk is required, the application builder may not feel the need to fully understand the MVC methodology. The use of view-Builder is described at the end of this chapter.

## View Components and Their Capabilities

The next sections of this chapter deal with specific types of prebuilt components in ST-80 which can be used for building user applications.

## 8.2 The View Framework

Figure 8.2 displays several different views that often might appear as composite parts in an application in a window. This view shows a gauge, a button, a switch, a selection-in-list, a text editor view, and a transcript. The use of each of these views is described in some detail in the following discussion. This figure will also serve as an example for the viewBuilder methodology
<figure><img src="image_96.png" /><figcaption>Figure 8.2 Six Example Views in a Window. Reading clockwise from left: gauge, transcript, list, switch, button, and text views.</figcaption></figure>

described in the latter part of the chapter. The task of the programmer is to create applications that typically consist of either single or multiple windows filled with views, some of which may be coordinated with the models linked to view/controller pairs.

To implement a new application view, the standard methodology is to create a class method in the view or model class of an application, usually called “open” or “openOn: anObject.” As indicated previously, an instance of the class ScheduledWindows is created in this method to provide the interface to the host operating system and views added one by one as compositeParts of the window.

The message *openOn: anObject* can be used in preference to *open* to permit passing “anObject” to the opening of an application. This type of opening message can be used when data is passed to the application. For example, an application could be envisioned that displays the contents of any dictionary. In this type of example, the application could be opened on the contents of different dictionaries to display different contents each time the *openOn: aDictionary* message is sent to the application class. If *openOn: anObject* is sent as a message to a view class, it is useful to let the object passed as the parameter to *openOn*: be an instance of the model so that model methods and values are easily accessible to the view. In contrast, if “openOn:” is a class method in the model, the argument to *openOn*: might well be
"self new" to permit the remaining code in the opening method to access an instance of the model. For example,

open

"ExampleClass open"

openOn: self new

openOn: anInstanceOfanExampleClass

...

window open

"A method in the model"

"A comment that runs the example"

"Code that calls the"

"openOn: method" "with"

"an instance of the model"

"as an argument"

In this example, the utility of passing the argument *anInstanceOfanExampleClass* to the *openOn:* method is to have access to the instance variables of the class within the *openOn:* method. It is also worth noting that the creation and opening of windows can be accomplished either in a model class or a view class. The advantage of opening an application in a model class is that it is somewhat conceptually clearer to (1) create the view from the model and then (2) only operate within the model, sending *update* messages whenever the view should update itself.

## Creating Views in Version 2.5

The creation of application views in Version 2.5 of ST-80 is quite similar to the method for creating views within the host windows of Release 4 as described previously. Next, the basic scheme for opening views in Version 2.5 is discussed for historical interest. Readers with no need to understand the relationship of Version 2.5 views and Release 4 views can skip the next paragraph.

To implement a new application view, the standard methodology is to create a class method in the view class, typically the "open" or "openOn: anObject." The *open* method normally contains a definition of the topView as a StandardSystemView with information about the border, the label, and the model, if any. A "topView" is roughly equivalent to a window in Release 4 and the class **StandardSystemView** provides windowing protocol for subclasses. Subviews are then individually defined and added to the topView. Subviews correspond to window components in Release 4. When the programmer completes these definitions, the controller for the topView is opened to create the
view on the screen. The general form typically followed is

<table><tr><td>open</td><td>"A class method in a view class"</td></tr><tr><td>"ClassNameView open"</td><td></td></tr><tr><td>|topView|</td><td>"local variable"</td></tr><tr><td>topView := StandardSystemView</td><td></td></tr><tr><td>model: nil</td><td>"no model specified"</td></tr><tr><td>label: 'a label string here'</td><td>"a label"</td></tr><tr><td>minimumSize: 50@50.</td><td>"specify the minimum"</td></tr><tr><td></td><td>"size window"</td></tr><tr><td>topView borderWidth: 2.</td><td>"the width of the view border"</td></tr><tr><td>topView addSEMBView (GClockView new)</td><td>"add a clock"</td></tr><tr><td>in: (0.0@0.0 extent: 1.0@1.0)</td><td>"the location in the view"</td></tr><tr><td>borderWidth: 1.</td><td>"the border width"</td></tr><tr><td>topView controller open</td><td>"open the view"</td></tr></table>

In this simplified example, topView is a **StandardSystemView** with no model. Any label can be used and the minimumSize set to give the minimum size window when the view is opened. In this example, a new graphical clock<fnref n="1" /> is created and added to the topView, covering the entire extent of the topView. Finally, topView is sent the message "controller" to get the default controller for the view and "open" is sent to the controller to open the view.

## 8.3 Selection-in-List

For selecting items, a pluggable view implemented in the class **SelectionInListView** is available in ST-80. A selection-in-list provides the capability of presenting to the user a scrollable list of items, from which any item can be selected using the mouse. When a selection-in-list view is opened, the user plugs into the opening method information about the model in which information resides and what to do when the user operates the list. For example, when the user makes a new selection, both the model and the methods within the model that take action when the selection occurs must be designated. The pluggable view approach provides a very useful interfacing technique which bypasses the need for the user to create explicit MVC linkages. Instead, these linkages are built by the code within the pluggable view. As an example, the creation

<footnote n="1">¹Note that **GClockView** was a Version 2.5 class that used a pen to create a display of a clock. This class does not exist in Release 4.</footnote>
message used for class **SelectionInListView** is

`on:aspect:change:list:menu:initialSelection:`

An instance of a selection-in-list view is created by sending this message to the class **SelectionInListView**. Then, the instance view created is added as a composite part to the window. For example, consider the following list that is built to show a list of pictures to display. Each of the arguments for the `on:aspect...` message is explained later.

listView := SelectionInListView
    on: aModel
    aspect: #picture
    change: #picture
    list: #pictureList
    menu: #pictureMenu
    initialSelection: #pictureSelection

The argument to `on:` is the object to which messages are sent by the remaining arguments in the `on:aspect...` message. Note that if `aModel` were replaced by `self`, any messages would be sent to the same class or class instance in which this code appeared. `Aspect` refers to which aspect of an object is of concern. For example, an object containing several types of information could be passed to `on:`. The `aspect` might then refer to one of the object's internal data structures or instance variables. In the case of **SelectionInListView**, the aspect selector (i.e., the symbol used to make a selection; in this case, `#picture`) can be used as the argument for updating something connected to the list. The argument to `changed:` is the selection that the user makes from the list that is passed to the method (in this example, `#picture: aSelection`.) specified in `aModel`. Each time a new item in the list is selected by pointing and clicking, `#picture: aSelection` is sent to aModel in this example. The argument to `menu:` is the message that is sent to get the menu and the argument to `initialSelection:` is the message to be sent to select one of the items in the list, when the list is first created. If `nil` is the argument to `initialSelection:`, no initial selection will be made. `pictureList` is the method that returns a collection of items that is to be displayed in the list and `pictureMenu` returns a menu that is to be associated with the operate key of the mouse. The
"#" signs denote the named items as symbols. An example of the use of **SelectionInListView** is given later in the chapter.

## 8.4 Buttons and Switches

Buttons and switches can be created by sending new messages to the class **LabeledBooleanView**, a subclass of **BooleanWidgetView**. Different functionality for buttons and switches is provided, such as checkboxes, radio buttons, simple switches, and toggle switches. A button has the functionality of setting the model linked to it (a valueHolder) to be true only while the mouse select button is pressed. In contrast, a switch sets the model to be true or false on successive presses of the switch.

An example of creating a button is as follows:

<table><tr><td>aButton := LabeledBooleanView new.</td><td>"provide true and false output"</td></tr><tr><td>aButton beTrigger.</td><td></td></tr><tr><td>aButton controller beTriggerOnUp</td><td>"provide a state change when"<br>"the user releases the button"</td></tr></table>

aButton beVisual: 'THE TEXT TO BE DISPLAYED' asComposedText.

aButton model:

<table><tr><td>((PluggableAdaptor on: aModel)</td><td>"specify the view-model link"</td></tr><tr><td>getBlock:</td><td>"the message to send to change"</td></tr><tr><td>[:model | model getMethod]</td><td>"the button"</td></tr><tr><td>putBlock:</td><td>"the message to send the model"</td></tr><tr><td>[:model :value | model putMethod]</td><td></td></tr><tr><td>updateBlock:</td><td>"when the button is pressed"</td></tr><tr><td>[:model :value :parameter | false])</td><td></td></tr></table>

To add this button to a container, one could write:

container add: aButton
in: (0.0@0.0 extent: 0.1@0.1).

within the opening method prior to opening the window. This code will install the button in the upper left part of the window with x and y directions extending to 10 percent of the window size in the x and y directions.

The class **PluggableAdaptor** is used to create an interface between view/controller pairs and a model, in this case, the button view/controller and the model. A model is passed through the adaptor (aModel) which contains the
methods mentioned in the blocks, that is, "getMethod" and "putMethod." The code executed by sending `getMethod` to the model is used to acquire the current state of the model. This knowledge might be useful in dynamically adapting the appearance of the button, depending on information in the model. The method referenced within the `putBlock:` will be executed whenever the button is pressed. Finally, the `updateBlock` arranges for updates from the model, passing the model, an update aspect, and an update parameter. In this case, the value returned in the update block is always false, indicating that no updating is to be done.

## 8.5 Transcripts and Text Editors

A transcript permits a program to output information as text to a view. An example is the system transcript to which messages can be sent. The system transcript is useful for debugging purposes, in that messages such as "Transcript show: 'message about an error'" can be placed in different parts of a program. The global variable "Transcript" is bound to the system transcript. To create one's own transcript or multiple transcripts for showing different things, the code is straightforward:

```sfml
aTranscript := TextCollector new.
```

```sfml
aTextCollector := TextCollectorView open: aTranscript label: 'FFt Information Window'.
```

```sfml
aTranscript show: 'Processing is starting now'.
```

By declaring the instance of `TextCollectorView` as global, the `textCollector` can be sent information from any part of an application. Furthermore, the `textCollector` view can be installed as a `compositePart` in an application window, as needed.

A text editor can be created using the `CodeView` class, as follows:

<table><tr><td>aTextEditorView</td><td>CodeView</td></tr><tr><td>on:</td><td>aModel</td></tr><tr><td>aspect:</td><td>#initText</td><td>"get initial text to show"</td></tr><tr><td>change:</td><td>#acceptText</td><td>"method to run"</td></tr><tr><td>menu:</td><td>#textMenu</td><td>"when text change accepted"</td></tr><tr><td>initialSelection:</td><td>nil.</td><td>"specification of menu"</td></tr><tr><td></td><td></td><td>"no initial selection"</td></tr></table>

Opening class `CodeView` on "aModel" means that the methods referenced by the selectors specified in `aspect:change:menu:initialSelection` should be within
object "aModel." Other objects could be specified as the argument to "on:," for example "self." By specifying "self," the user would explicitly indicate that the methods specified as arguments to the **CodeView** would be within the class or class instance in which the **CodeView** creation occurred. Once specification of this **CodeView** instance is made, it can be added as a view to the window. The instance of **CodeView** created permits the standard text editing operations including: copy, cut, paste, and so on.

## 8.6 Building Menus

### PopUpMenus

**PopUpMenu** is an easy-to-use class that gives the programmer the capability of creating pop-up menus with a simple class specification as follows:

(PopUpMenu labels: 'first item \ second item \ third item' withCRs) startUp.

Highlighting this code and executing "doit" will produce a menu. Execution (i.e., clicking on an item in the list) will return a number equivalent to the position in the list, starting with 1. In this example, carriage returns are added after each item in the string "first... item" by sending "withCRs" to the string.

### Dialogs

A set of classes are provided in ST-80 that make it easy to build dialog boxes. For example, there are prefabricated classes for creating yes-no prompters, fill-in-the-blank (one and two lines) prompters, and labeled menus with scroll bars. These dialog boxes are of the pop-up variety, appearing on demand and disappearing after use. The main types are created as follows:

<table><tr><td>Yes/No Prompter:</td><td>DialogView confirm: 'Is the voltage greater than 5V?'.</td></tr><tr><td>FillInTheBlank:</td><td>DialogView request: 'What is your name?'.</td></tr><tr><td>Menu:</td><td>DialogView show: aMenu withLabel: 'Pick one of the following'.</td></tr><tr><td>ButtonMenu:</td><td>DialogView showChoice: aMenu withLabel: 'Pick one of the following'.</td></tr></table>

In the latter two types, aMenu could be a **PopUpMenu** created as shown
<figure><img src="image_97.png" /><figcaption>Figure 8.3 FillInTheBlank Pop-up View and Dialog View.</figcaption></figure>

previously without the *startUp* message. These dialog views are similar to the **FillInTheBlank** class implemented in earlier releases of ST-80 (Version 2.5 and earlier). **FillInTheBlank** is found in backward compatibility fileIns for Release 4. Figure 8.3 shows the results of issuing the code to create an instance of this class:

FillInTheBlank

request: 'What is the Voltage at P2?'

displayAt: Sensor waitButton

centered: true

action: [:response | Transcript show: 'response']

initialAnswer: '5 volts'.

The request in this example is a question asked the user. The pop-up window is displayed at the cursor (called a sensor) as soon as a button is pressed with the cursor centered in the view. The information that the user types is passed to the *action: aBlock* shown. For this block, the response is simply typed on the transcript. One can also specify an initial default answer as shown. Also shown in Figure 8.3 is the same style FillInTheBlank prompter implemented using
<figure><img src="image_98.png" /><figcaption>Figure 8.4 LauncherView with User Additions.</figcaption></figure>

DialogView in Release 4. The implementation is somewhat simpler than the
previous implementation; that is,

DialogView request: 'What is the voltage at P2??' initialAnswer: '5 volts'.

## Hierarchical Menu

The methodology of creating a hierarchical menu was shown in Figure 7.11. This paragraph presents a method for adding to the hierarchical menu of the Launcher. Figure 8.4 shows a modified **LauncherView** with three additional entries that can be used to launch the applications named. The method for modifying the Launcher is to edit, accept, and reinitialize code in the LauncherView. Specifically, the method *initializeLauncherMenu* can be easily modified to add additional items to the Launcher list. Although the code in this method is implemented using PopUpMenus, a hierarchical menu could be just as easily used. Customizing the Launcher is an excellent way to organize the environment.

## 8.7 Using Forms

A form is a black-and-white image that contains bits which, when set, indicate where black and white dots are shown within a rectangle displayed on the screen. Forms are a display technique used with the ST-80 environment in Version 2.5 and earlier. As indicated in the previous chapter, forms have been replaced with images to provide color capabilities in later releases of the ST-80
environment. However, forms can still be used in the later releases. A form created in an earlier version can be read from a file and converted to an image and then displayed on the graphics context<fnref n="2" /> of the window. For example,

`aForm := (Form readFrom: 'and.frm') asImage.`

`aForm displayOn: aView graphicsContext borderedIn: (0.5@0.0 extent: 0.3@0.5).`

## 8.8 Using Images

Release 4 of Smalltalk-80 was the first release of the environment to support commonly used pixel-based images. As indicated previously, prior to 1990, ST-80 used forms, consisting of rectangular displays of on-off bits, to provide graphics. Unfortunately, using images which permitted only turning a bit on or off at each pixel precluded the use of color, which requires multiple bits at each pixel. Hence, a change was made to include color in Release 4 and future releases.

The ST-80 Environment supports a hierarchy of classes to support the creation of images:

<table><thead><tr><th>Object</th><th></th></tr></thead><tbody><tr><td><strong>VisualComponent</strong></td><td></td></tr><tr><td><strong>Image</strong></td><td></td></tr><tr><td>Depth1Image</td><td>"equivalent to a Form"</td></tr><tr><td>Depth2Image</td><td></td></tr><tr><td>Depth4Image</td><td></td></tr><tr><td>Depth8Image</td><td></td></tr><tr><td>Depth16Image</td><td></td></tr><tr><td>Depth24Image</td><td></td></tr></tbody></table>

The depth in these classes refers to the number of bits per pixel. One bit per pixel is the same as found in a black-and-white form. Two bits permits storage of 4 different colors, four bits, 16 colors, and so on. One can create images by sending class **Image** messages, for example,

`Image extent: anExtent depth: aNumber palette: aPaletteOfColors`

where extent is the size of the image, depth is {1, 2, 4, 8, 16, or 24}, and palette

<footnote n="2">²A graphics context contains parameters that affect graphics operations.</footnote>
permits specification of the colors in the image. Another alternative is to simply
use the *fromUser* message to class **Image** to grab a form from the screen. Of
course, to use the different **Depth*Image** classes with *fromUser*, one should
know the depth of the image that can be represented on the screen of the host
platform.

8.9 Building and Using Icons

Icons are small graphics representations that are used to provide the user with an abstract reminder about information underlying an icon. Icons are predominantly used in ST-80 for representing what is in a collapsed window. For example, an icon of the system browser might be a drawing that has the miniaturized appearance of a tree structure. Alternatively, an icon might be simply a textual name inserted into a box. In ST-80, when a window is collapsed, an icon appears and can be moved to different locations on the screen. Thus, one can keep on the desktop many collapsed windows that are readily accessed simply by clicking on the icon. Icons have different appearances depending on the platform on which ST-80 is running. For example, on the Macintosh, the standard icon is simply the name in the label field of the window. On other platforms, graphics representations of icons can be created that give a visual cue about the contents of the collapsed window.

One way to create an icon is to duplicate the methods outlined in the **Icon** class in methods such as *createProjectIcon* or *createDebuggerIcon*. In these icons, individual bits in hexadecimal form are specified (e.g., "16rFF" represents the number FF₁₆). Examine one of the preceding methods in the browser and compare the hex-specified bits with the icon that appears when a window is iconified. Already included in the system is a dictionary of IconConstants for all the window types of ST-80. To create a new icon, a reasonable example in the system to follow is the Launcher icon. The method *createLauncherIcon* in **Icon** retrieves a depth1 image which is created in the method *initializeGatewayImage* in the **LauncherView** class. If one examines the way that the Launcher icon is created by specifying 1's and 0's in radix 2 eight-bit representation (e.g., "2r00001111" represents 00001111₂), the icon of the Launcher on the screen can be observed to map directly to the bits shown in the *initializeGatewayImage* method. Hence, to create a new icon, all that is necessary is to edit this type of bitmap and install it into the IconConstants dictionary, following the methodology shown for the other icons. To test what an icon would look like, one can use code in a workspace such as

ScheduledControllers activeController view icon:
(Icon image: (Icon createTestIcon)).
<figure><img src="image_99.png" /><figcaption>Figure 8.5 Using Icons in a Circuit Representation.</figcaption></figure>

where *createTestIcon* is a method similar to *createLauncherIcon* except that a different test image should be created by the user following the image creation method outlined in the **LauncherView** class. In this example, the code "ScheduledControllers activeController view" returns the view in the workspace in which the code was entered. Once the preceding code is executed (i.e., "doit") in the workspace, the icon can be viewed by collapsing the workspace.

Not only do icons permit graphic representation of entities, the ability to expand collapsed views that have graphical identities has the potential for creating interesting user interfaces. For example, one might create views of hierarchical designs of electronic systems by creating collapsed views of electronic gates which, when expanded, would show the internal structure of the gates. Figure 8.5 shows an example of this concept.

## 8.10 Other View Components

Various other types of view components are both available and conceivable. Pluggable views can be written similar to the pluggable views available in the system itself. For example, Knowledge Systems Corporation (Adams, 1987) marketed a package called Pluggable Gauges with which one could create
many types of interesting gauges.<fnref n="3" /> For example, to create a bar gauge as shown in Figure 8.2, a pluggable view can be created as follows:

`numberHolder := NumberHolder new value: 30.`

```ruby
BarGaugeWithScaleView
    on: numberHolder
    aspect: #value
    change: #value:
    range: (0 to: 55 by: 5)
    orientation: #vertical
    needleDirection: #right.
```

NumberHolder is a simple object that contains values and uses the methods "value" and "value:" to access and set the internal value of numberHolder. Note that the gauge is opened on numberHolder. This means that the selectors in *aspect*: and *change*: are found in numberHolder. The remaining three values for range, orientation, and needleDirection are passed to set up the BarGauge view. The point worth noting here is that the concept of pluggability is fully extensible; that is, most kinds of views that can be varied using different parameters could be set up in this manner.

## 8.11 Putting the Components Together

In the previous sections that have examined the use of different view components, only code fragments were shown. Two complete examples will be shown next to illustrate the direct and pluggable implementation methods.

### Direct Implementation of the MVC

This example is concerned with creating a view with a pop-up menu which contains a list of different colors that can be displayed on the view. In this example, two colors are used: blue and red. Figure 8.6 shows the screen appearance of the window created and Table 8.1 gives the code that implements

<footnote n="3">³See the Appendix for information about securing a Release 4 gauge package based on Adams' work.</footnote>
<figure><img src="image_100.png" /><figcaption>**Figure 8.6** Example Use of the MVC Methodology for Showing Different Colors in a Window. When *red* is selected, the interior of the window turns red. When *blue* is selected, the interior turns blue. Note in this black-and-white printing that colors appear with different patterns (e.g., the interior and exterior of the window shown).</figcaption></figure>

this window. The colors are produced in this black-and-white figure as different textures. Three classes are implemented: **DisplayDemo**, **DrawingController**, and **DrawingView**. The most direct way to understand the operation of the triad is to examine first the *open* method in **DrawingView** which follows closely the methodologies outlined in the previous examples. A model instance is created from the class **DisplayDemo** and a view instance is built which is linked to the model and the controller. A window is created as an instance of **ScheduledWindow** and opened.

In operating this example, the user selects an item from the pop-up menu associated with the controller. After the user chooses a selection, the choice is sent to the model from the controller. In the model, an image of the size of the display is created and the specified color created on a new image is stored in an instance variable called *displayImageSurface*. After drawing is complete, the view is notified that the model is changed (i.e., via the message *self changed*). The view that is linked to the model receives the information that the model has been changed via the *update* message. In this example, *update* simply retrieves the image to display and displays the image, using the *displayOn* method on the graphicsContext of the view. Figure 8.7 graphically
<table><caption>**Table 8.1** The DrawingView Example</caption><thead><tr><th colspan="2">The View</th></tr></thead><tbody><tr><td><strong>View subclass:</strong></td><td><code>#DrawingView</code></td></tr><tr><td><strong>InstanceVariableNames:</strong></td><td>'displayImage'</td></tr><tr><td><strong>classVariableNames:</strong></td><td>"</td></tr><tr><td><strong>poolDictionaries:</strong></td><td>"</td></tr><tr><td><strong>category:</strong></td><td>'book demos'</td></tr></tbody></table><p>This example shows a basic model-view-controller set of classes for creating a pop-up menu in a view in a window which permits selecting "blue" or "red." When selected, the interior color of the view changes to the color selected.</p><p><strong>DrawingView methodsFor:</strong> displaying</p><table><thead><tr><th colspan="2">displayOn: graphics Context</th></tr></thead><tbody><tr><td><code>displayOn:</code></td><td>displays the image in the model in the view</td></tr><tr><td><code>self model displayImage displayOn:</code></td><td><code>self graphicsContext</code></td></tr></tbody></table><table><thead><tr><th colspan="2">update: graphicsContext</th></tr></thead><tbody><tr><td><code>update</code></td><td>responds to the changed message from the model</td></tr><tr><td><code>self displayOn: graphicsContext</code></td><td></td></tr></tbody></table><p><strong>DrawingView class</strong></p><table><thead><tr><th colspan="2">instanceVariableNames:</strong></th></tr></thead><tbody><tr><td><code>aModel</code></td><td><code>'define local variables'</code></td></tr><tr><td><code>aModel := DisplayDemo new.</code></td><td><code>"create the model instance"</code></td></tr><tr><td><code>aModel initialize.</code></td><td><code>"initialize the model"</code></td></tr><tr><td><code>aView := DrawingView new</code></td><td><code>"create DrawingView instance"</code></td></tr><tr><td><code>setModel: aModel.</code></td><td><code>"connect the model and view"</code></td></tr><tr><td><code>aView controller: (DrawingController new).</code></td><td><code>"make a controller"</code></td></tr><tr><td><code>aWindow := ScheduledWindow new.</code></td><td><code>"make a new window"</code></td></tr><tr><td><code>aWrapper := BorderedWrapper on: aView.</code></td><td><code>"with a border"</code></td></tr><tr><td><code>aWindow minimumSize: 200@200.</code></td><td><code>"define minimum size"</code></td></tr><tr><td><code>aWindow label: 'MVC and Color'.</code></td><td><code>"the label on the window"</code></td></tr><tr><td><code>aWindow component: aWrapper.</code></td><td><code>"add the wrapper to the window"</code></td></tr><tr><td><code>aWindow open</code></td><td><code>"open the window"</code></td></tr></tbody></table><p><strong>The Model</strong></p><table><thead><tr><th colspan="2">Model subclass:</strong></th></tr></thead><tbody><tr><td><code>#DisplayDemo</code></td><td><code>'displayImageSurface'</code></td></tr><tr><td><strong>instanceVariableNames:</strong></td><td>'displayImageSurface'</td></tr><tr><td><strong>classVariableNames:</strong></td><td>"</td></tr><tr><td><strong>poolDictionaries:</strong></td><td>"</td></tr><tr><td><strong>category:</strong></td><td>'book demos'</td></tr></tbody></table>
Table 8.1 Continued

### DisplayDemo methodsFor: drawing

#### drawBlue: size

"Defines the image and color to display"

displayImageSurface := Image
extent: size extent
depth: 1
�apelette: (Mapped with: ColorValue Blue with: ColorValue red).
self changed "indicate that there has been a change in the model"

#### drawRed: size

"Defines the image and color to display"

displayImageSurface := Image
extent: size extent
depth: 1
�apelette: (Mapped palette with: ColorValue red with: ColorValue blue).
self changed

### DisplayDemo methodsFor: retrieving

#### displayImage

"returns the image to display"

^displayImageSurface

### DisplayDemo methodsFor: initialization

#### initialize

"Initializes this class"
"A the display is green when the Drawing view is first shown"

displayImageSurface := Image
extent: 300@300
depth: 1
�apelette: (Mapped palette with: ColorValue green with: ColorValue blue)

## The Controller

ControllerWithMenu subclass: #DrawingController
instanceVariableNames:"
classVariableNames: 'Drawing YellowButtonMenu'
poolDictionaries:"
category: 'book demos'

### DrawingController methodsFor: access

#### menu

^DrawingYellowButtonMenu
<table><caption>**Table 8.1 Continued**</caption><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>DrawingController methodsFor: menu items</td><td></td></tr><tr><td>drawBlue</td><td>"draw a blue view"<br/>self model drawBlue: self view bounds</td></tr><tr><td>drawRed</td><td>"draw a red view"<br/>self model drawRed: self view bounds</td></tr><tr><td>DrawingController class instanceVariableNames:</td><td>"</td></tr><tr><td>DrawingController class methodsFor: initialization</td><td></td></tr><tr><td>initialize</td><td>"DrawingController initialize"<br/>"Defines the pop-up menu and the methods to associate with menu labels"<br/>DrawingYellowButtonMenu := PopUpMenu labelList: #(#(red#blue))<br/>values:#(drawRed#drawBlue)</td></tr></tbody></table>

illustrates the linkages between the various components in the MVC triad of this example.

## Using Inspectors

A method for examining model-view-controller triads is to inspect the model, view, and controller instances that are used to create an application; for example, the instances of **DrawingView**, **DrawingController**, and **DisplayDemo**. Figure 8.8 shows the collection of inspectors for each of these MVC elements. Each window displays a dictionary with scrollable keys on the left and the contents of a selected key on the right in each window. The keys of the dictionaries contain information about each of the members of the MVC triad. For example, in the **DrawingView**, the value in the key "controller" indicates that the controller is a **DrawingController**. To inspect a running application, one can place "self halt" in the code somewhere and run the application. When a halt occurs, in the debugger, select the view, model, or controller in the object lists at the bottom of the debugger and, from the operate menu, select "inspect"
<figure><img src="image_101.png" /><figcaption>**Figure 8.7** The DisplayDemo Example Model-View-Controller and Control Linkages. (Solid lines = messages, dotted lines = changed/update messages.)</figcaption></figure>

to produce any or all of the MVC inspectors. These inspectors are useful in debugging and checking to see if all the proper linkages have been made.

## Pluggable Implementations

A pluggable implementation is illustrated in Figure 8.9 which displays a window with two views: a **SelectionInListView** at the top and a **View** with a bordered wrapper at the bottom. The purpose of this example is to show how to display, in the view at the bottom of the window, a named image that is selected from items in the selection-in-list. The two images captured for this example were simply taken from the screen using *Image from User*. This example is
<figure><img src="image_102.png" /><figcaption>Figure 8.8 A Triad of Inspectors for Examining the Model, View, and Controller.</figcaption></figure>

implemented in class **PictureView**, a subclass of **View**, and uses a global variable "PictureDictionary" to hold images. One could create a scrapbook of pictures using the technique. Table 8.2 shows the code used to implement **PictureView**. The most distinct characteristic of this code, as contrasted with the implementation of **DisplayDemo**, is the lack of explicit specification of the three parts of the MVC triad. Instead, the entire code is contained in this single class. The major work is done in the *openOn* method. First, a window is created and the selection-in-list view built. Next, an imageView is created as an instance of **View** and both views added before opening the window. The selectors in the **SelectionInListView** refer to the remaining methods in the **PictureView** class, listed under the "menu items" protocol. An *update* method is not used in this implementation because the selection of an item in the menu causes direct display of the image in the imageView graphicsContext each time a selection is
<figure><img src="image_103.png" /><figcaption>**Figure 8.9** Plugging in Multiple Views: the ** PictureView** Example. In this example, selecting "ribbons" or "chess" will display a picture of ribbons or chess pieces.</figcaption></figure>

made. Note that without an *update* method, however, the image will disappear from the window if the window is moved on the screen. This problem can be avoided by simply adding an *update* method which contains the following code:

```python
self picture displayOn: imageView graphicsContext.
```

By adding this code, when an *update* method is sent to the view due to, for example, moving the window on the screen, the current picture in the object will be redisplayed in the view.

It is, in general, simpler and more direct to use the “pluggable” methodologies rather than the direct implementation method of constructing an
<table><caption>**Table 8.2** The PictureView Example</caption><thead><tr><th>View subclass:</th><td>#PictureView</td></tr></thead><tbody><tr><td>InstanceVariableNames:</td><td>'imageView currentPicture'</td></tr><tr><td>classVariableNames:</td><td></td></tr><tr><td>poolDictionaries:</td><td></td></tr><tr><td>category:</td><td>'book demos'</td></tr><tr><td>PictureView methodsFor:</td><td>menu items</td></tr><tr><td>picture</td><td></td></tr><tr><td>^currentPicture</td><td></td></tr><tr><td>picture: aPicture</td><td>currentPicture := PictureDictionary at: aPicture ifAbsent: [^ nil].<br/>currentPicture displayOn:chtView graphicsContext</td></tr><tr><td>pictureList</td><td>^PictureDictionary keys asOrderedCollection</td></tr><tr><td>PictureView methodsFor:</td><td>instance creation</td></tr><tr><td>openOn: aPictureDictionary</td><td>"PictureView new openOn: PictureDictionary"<br/>|window listView aCompositePart| "specify the local variables"<br/>window := ScheduledWindow new. "make a new window"<br/>window label: 'Picture Dictionary'. "with a label"<br/>window minimumSize: 300@300. "define the minimum size"<br/>aCompositePart := CompositePart new. "create a holder for the parts"<br/>chtView := View new. "a new view"<br/>listView := SelectionInListView on: self "make a list"<br/>aspect: nil "no aspect"<br/>change: #picture: "send picture: when there is a change"<br/>list: #pictureList "get the list from pictureList"<br/>menu: nil "there is no menu"<br/>initialSelection: nil. "and no initial selection"<br/>aCompositePart add: (LookPreferences edgeDecorator on: listView)<br/>in: (0@0 extent: 1@0.3). "make the list scroll and designate"<br/>aCompositePart add:chtView "where it is to be located"<br/>borderedIn: (0@0.3 extent: 1@0.7). "add the image to the composite part"<br/>window component: aCompositePart. "add the view to the window"<br/>window open "open the window"</td></tr><tr><td>PictureView class<br/>InstanceVariableNames:</td><td>"PictureView new openOn: PictureDictionary"</td></tr><tr><td>PictureView class methodsFor:</td><td>initialize</td></tr><tr><td>setup</td><td>"PictureView setUp"<br/>PictureDictionary := Dictionary new. "make a new global dictionary"<br/>PictureDictionary at: #ribbons put: (Image fromUser).<br/>PictureDictionary at: #chess put: (Image fromUser).<br/>Logo := Image fromUser.</td></tr></tbody></table>
individual model, view, and controller. Following this line of reasoning, it is even simpler to use a graphical editor for creating the desired view. A building system for creating views has been constructed and is described next.

## 8.12 ViewBuilder<fnref n="4" />

ViewBuilder is a graphics programming system designed to permit users to create ST-80 view frameworks without having to create any code. First described by Jiang and Bourne (1991) in a Version 2.5 implementation, this system requires little knowledge about the MVC triad to create useful views that employ the view components described previously. Figure 8.10 displays the ViewBuilder interface for Release 4. Arrayed on the left side of the figure are buttons that initiate different actions including create, move, remove, resize, relabel, save, load, and compile. To create a new view, the user selects create and sizes the view to be built on the view to the right of the buttons. Next, an operate-button-connected pop-up menu permits selection of any of the types of views that can be added to the window such as `SelectionInListView`, `TextCollectionView`, or `CodeView`. The example in the figure shows building a window that contains six different types of views implemented in the system. The user simply selects the desired view type from the pop-up menu and sizes and places the view within the window. After selection of the view components is complete, the "compile" button is pressed. ViewBuilder takes the stored information built during creation of the placement of the types of views and inserts the information into sets of prototypical strings which are amalgamated to form the code of the completed view. Figure 8.2 is the result of the compilation of the skeletal form in Figure 8.10. The complete code for the view is generated and added to the ST-80 system, appearing in the system browser view as shown in Figure 8.11. The category in the browser is named according to a name given by the user when the ViewBuilder is opened. The classes built are designated with the name given by the user for the class with a prepended "V" and postpended "Controller" and "View" strings. The complete code built for this example is shown in Table 8.3. The reader is encouraged to compare the code in this table with the final view created as shown in Figure 8.2. Once this skeleton code is available, the programmer simply edits the code to create the application characteristics desired. For example, to add behavior to a button or switch, the user can simply pass arguments to the button or switch (see `self.button:act:model:container:in:` in the `open:` method of `VBExampleView`) or specify the behavior in the model. Comments in the code give additional details

<footnote n="4">⁴See the Appendix for information on obtaining ViewBuilder code.</footnote>
<figure><img src="image_104.png" /><figcaption>Figure 8.10 The ViewBuilder Interface.</figcaption></figure>
<figure><img src="image_105.png" /><figcaption>Figure 8.11 The Result of Compilation Using ViewBuilder.</figcaption></figure>
<table><caption>**Table 8.3** Code from ViewBuilder</caption><tr><td>View subclass:</td><td>#VBExampleView</td></tr><tr><td>instanceVariableNames:</td><td>"classVariableNames:"><br>"poolDictionaries:"><br>"category: 'Builder-Example'"</td></tr><tr><td colspan="2">This class is the view class produced by ViewBuilder. The open method opens the application using an instance of VBExample, which is referred to by "aModel" in the open: aModel method.</td></tr><tr><td>VBExampleView methodsFor:</td><td>private</td></tr><tr><td>defaultControllerClass</td><td>^VBExampleController</td></tr><tr><td>VBExampleView methodsFor:</td><td>displaying</td></tr><tr><td>displayOn:</td><td>nothing</td></tr><tr><td colspan="2">"This method can be used to update views in VBExampleView. An update method with anAspect can be added in this Class to specify which aspect of the view to update, if desired"</td></tr><tr><td colspan="2">self display Text: ('Display object using method &lt;displayOn: aGC&gt; in category &lt;displaying&gt; in instance methods in class', self class yourself printString) as ComposedText</td></tr><tr><td>displayText:</td><td>aText</td></tr><tr><td colspan="2">"This is how to display text"</td></tr><tr><td colspan="2">self graphicsContext clear.</td></tr><tr><td colspan="2">aText compositionWidth: self insetDisplayBox width.</td></tr><tr><td colspan="2">aText displayOn: self graphicsContext</td></tr><tr><td>VBExampleView class</td><td>InstanceVariableNames:"</td></tr><tr><td>VBExampleView class methodsFor:</td><td>subViews</td></tr><tr><td>button: aLabel act: act model: aModel container: aContainer in: aRange</td><td>"This message implements a button"<br>"'act' is sent to 'aModel' in PluggableAdaptor"<br>"'act' and 'aModel' are specified in the open: aModel method"<br>"The 'act' can be specified in a method in VBExample"<br>"aModel is an instance of VBExample-see open method in VBExampleView"</td></tr><tr><td>aButton</td><td>aButton := LabeledBooleanView new.<br>aButton beTrigger.<br>aButton controller beTriggerOnUp.<br>aButton beVisual: aLabel asComposedText.<br>aButton model: ((PluggableAdaptor on: aModel)<br>  getBlock: [:model|false]<br>  putBlock: [:model :value|model perform: act]<br>  updateBlock: [:model :value :parameter|false]).</td></tr></table>
<table><caption>**Table 8.3 Continued**</caption><thead><tr><th>Container</th><th>Property</th></tr></thead><tbody><tr><td>(aContainer)</td><td>add: aButton</td></tr><tr><td>in: aRange</td><td>borderWidth: 1)</td></tr><tr><td>insideColor: ColorValue</td><td>darkCyan</td></tr><tr><td>calendar: aContainer in: aRange</td><td>"This method requires class Calendar"</td></tr><tr><td>| aTextView|</td><td>aTextView: = CodeView</td></tr><tr><td></td><td>on: Calendar new</td></tr><tr><td></td><td>aspect: #calendar</td></tr><tr><td></td><td>change: #calendar</td></tr><tr><td></td><td>menu: #browseMenu</td></tr><tr><td></td><td>initialSelection: nil.</td></tr><tr><td>aContainer</td><td>add: (LookPreferences edgeDecorator on: aTextView) borderedIn: aRange</td></tr><tr><td>digitGauge: aComposite in: aRange val: valRange initial: initVal</td><td>aDGView: aDGGauge|<br/>aDGGauge: = NumberHolder new value: initVal.<br/>aDGView: = DigitGaugeView on: aDGGauge aspect: #value change: #value range: valRange.<br/>aComposite add: aDGView in: aRange borderWidth: 1.</td></tr><tr><td>gauge: aComposite o: orient t: type dir: dir in: aRange val: valRange color: aColor initial: initVal</td><td>aGauge|<br/>aGauge: = NumberHolder new value: initVal.<br/>BarGaugeWithScaleView<br/>on: aGauge aspect: #value change: #value: range: valRange<br/>orientation: orient type: type needleDirection: dir composite: aComposite<br/>in: aRange color: aColor.</td></tr><tr><td>hvview: aModel container: aContainer in: aRange</td><td>| aView|<br/>aView: = HVScrollView new model: aModel.<br/>aContainer<br/>add: ((LookPreferences edgeDecorator on: aView) useHorizontalScrollBar) in: aRange.</td></tr><tr><td>label: aLabel container: aContainer in: aRange</td><td>| aButton|<br/>aButton: = LabeledBooleanView new.<br/>aButton beTrigger.<br/>aButton controller beTriggerOnUp.<br/>aButton beVisual: aLabel asComposedText.</td></tr></tbody></table>
<table><caption>**Table 8.3 Continued**</caption><tr><td>aButton model: (<br/>(PluggableAdaptor on: self)<br/>getBlock: [:model|false]<br/>putBlock: [:model :value|false]<br/>updateBlock: [:model :value :parameter|false]).</td></tr><tr><td>(aContainer add: aButton in: aRange borderWidth: 1)</td></tr><tr><td>insideColor: ColorValue darkCyan.</td></tr></table>

**list: aModel container: aContainer in: aRange**

<table><tr><td>aListView</td></tr><tr><td>aListView := SelectionInListView</td></tr><tr><td>on: aModel printItems: false oneltem: false</td></tr><tr><td>aspect: #aspect change: #listChange: list: #list</td></tr><tr><td>menu: #listMenu initialSelection: nil.</td></tr><tr><td>aContainer</td></tr><tr><td>add: (LookPreferences edgeDecorator on: aListView)</td></tr><tr><td>borderedIn: aRange.</td></tr></table>

**switch: aLabel act: act off: act1 model: aModel container: aContainer in: aRange**

<table><tr><td>aButton</td></tr><tr><td>aButton := LabeledBooleanView new.</td></tr><tr><td>aButton beTrigger.</td></tr><tr><td>aButton controller beTriggerOnUp.</td></tr><tr><td>aButton beVisual: aLabel asComposedText.</td></tr><tr><td>aButton model: (<br/>(PluggableAdaptor on: aModel)<br/>getBlock: [:model|false]<br/>putBlock: [:model :value|</td></tr><tr><td>aButton insideColor = ColorValue darkCyan</td></tr><tr><td>ifTrue: [act isNil ifFalse: [model perform: act].</td></tr><tr><td>aButton insideColor: ColorValue red]</td></tr><tr><td>ifFalse: [act1 isNil ifFalse: [model perform: act1].</td></tr><tr><td>aButton insideColor: ColorValue darkCyan]]</td></tr><tr><td>updateBlock; [:model :value :parameter|false].</td></tr><tr><td>(aContainer add: aButton in: aRange borderWidth: 1)</td></tr><tr><td>insideColor: ColorValue darkCyan.</td></tr></table>

**textView: aModel container: aContainer in: aRange**

<table><tr><td>aTextView</td></tr><tr><td>aTextView := CodeView</td></tr><tr><td>on: aModel aspect: #text change: #acceptText:</td></tr><tr><td>menu: #textMenu initialSelection: nil.</td></tr><tr><td>aContainer</td></tr><tr><td>add: (LookPreferences edgeDecorator on: aTextView)</td></tr><tr><td>borderedIn: aRange.</td></tr></table>

**transcript: aTranscript container: aContainer in: aRange**

<table><tr><td>aTranscriptView</td></tr><tr><td>aTranscriptView := TextCollectorView new model: aTranscript.</td></tr></table>
<table><caption>**Table 8.3 Continued**</caption><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>aContainer</td><td>add: (LookPreferences edgeDecorator on: aTranscriptView)<br>borderedIn: aRange.</td></tr><tr><td>view: aModel container: aContainer in: aRange</td><td>|aView|<br>aView := self new model: aModel.<br>aContainer<br>add: (BorderedWrapper on: aView)<br>in: aRange</td></tr><tr><td colspan="2"><strong>VBExampleView class methodsFor: Instance creation</strong></td></tr><tr><td>open</td><td>"VBExampleView open"<br>self open: (VBExample new)</td></tr><tr><td>open: aModel</td><td>| window aComposite |<br>window := ScheduledWindow new. "make a new window"<br>window label: 'View Builder Example'.<br>window minimumSize: 367@174. "size selected by user created here"<br>aComposite := CompositePart new.<br>"next create a gauge"<br>self gauge: aComposite o: #vertical t: #bar dir: #right in: (0.0@0.0 extent: 0.212534@1.0)<br>val: (0 to: 50 by: 5) color: #blue initial: 25.<br>"create a button"<br>self button: 'Button' act: #button model: aModel container: aComposite in:<br>(0.212534@0.810345 extent: 0.351499@0.189655).<br>"create a switch"<br>self switch: 'Switch' act: #switchOn off: #switchOff model: aModel container: aComposite in:<br>(0.564033@0.810345 extent: 0.435967@0.189655).<br>"create a list"<br>self list: aModel container: aComposite in:<br>(0.762943@0.0 extent: 0.237057@0.810345).<br>"a text view"<br>self textView: aModel container: aComposite in: (0.212534@0.37931 extent:<br>0.550409@0.431034).<br>"and a transcript"<br>self transcript: aModel transcript container: aComposite in: (0.212534@0.0 extent:<br>0.550409@0.37931).</td></tr><tr><td>window component: aComposite.</td><td>window open</td></tr><tr><td>ControllerWithMenu subclass: #VBExampleController</td><td>InstanceVariableNames:"
"<br>classVariableNames:"
"<br>poolDictionaries:"
"<br>category: 'Builder-Example'</td></tr></tbody></table>
**Table 8.3 Continued**

This class contains the skeleton for specifying menu associated with the example.

**VBExampleController methodsFor: control defaults**

**menu**

```
^ PopUpMenu
    labels: 'Item\Item2\Item11\Item12' withCRs
    lines: #(2)
    values: #(#item1 #item2 #item 11 #item12).
```

**redButtonActivity**

view display Text: ('Mouse button message is located in category <control defaults> in instance methods in class called', self class yourself printString) asComposedText

**VBExampleController methodsFor: menu messages**

**item1**

view display Text: ('Menu messages are located in category <menu messages> in instance methods in class called', (self class yourself printString)) asComposedText

**Item11**

self item1

**item12**

self item1

**Item2**

self item1

**Model subclass: #VBExample**

InstanceVariableNames: 'transcript text'

classVariableNames: ""

poolDictionaries: ""

category: 'Builder-Example'

VBExample is the model created when an example MVC application is built. A protocol in the model that is associated with the views built provide "dummy" methods in which the user can insert specific code.

**VBExample methodsFor: text handling**

**acceptText: aText**

aText isNil ifTrue: [^ nil].

text := aText.

^ true

**text**

text isNil ifTrue: [text := 'Messages regarding text editor window is located in category <text handling>']