Computer operation generally requires controlled 'simultaneous' operation of more than one program. Such parallel threads of execution are called processes. Our definition of the concept of a process is that a process is a program that shares the CPU and other resources with other programs under the control of a process scheduler. VisualWorks processes use pre-emptive process scheduling which leaves a process to run until it terminates or suspends its execution or is suspended by a higher priority process or a semaphore. VisualWorks processes can be divided into two broad categories - system processes and user processes. Applications written by users and code segments executed from the workspace are normally executed as user processes and system processes include tasks such as garbage collection and input/output tracking.

VisualWorks processes are instances of class *Process*. Processes are always derived from blocks and the creation protocol can be divided into methods that create a process and schedule it for execution immediately, and methods that create a process but don't schedule it for execution. The first ones are defined in *BlockClosure*, the second in class *Process*.

Processes can be active, suspended, or terminated and the methods that change process state are `suspend`, `resume`, and `terminate`. Message `terminate` shuts down and destroys the process, `suspend` takes the process out of the queue of runable processes but does not destroy it, and `resume` puts a suspended process at the end of the queue of runable processes.

Every Smalltalk process has a priority expressed as an integer number between 1 (the lowest) and 100. User processes run by default at priority 50, I/O processes such as mouse and keyboard events run at priority 90, real-time processes run at priority 100, and system background processes run at priority 10. The `fork` creation message creates a *Process* at the priority of the parent process which created it, message `forkAt:` priority creates a *Process* at the specified priority. Both `fork` messages immediately schedule the new process which means that it is placed at the end of the queue of runable processes of their priority.

Smalltalk processes are managed by *Processor*, the single instance of class *ProcessScheduler*. *Processor* always selects for execution the first process in the highest priority non-empty queue of runable processes. Since *Processor* controls all priority queues, its protocol provides a very useful complement to other process control messages. Sending yield to *Processor* moves the currently active process to the end of its queue and activates the process at the head of the queue.

Processes often need to coordinate their operation in a way similar to traffic control at an intersection. Smalltalk's process coordination is based on analogy with traffic lights implemented by class *Semaphore*. The essence of the operation of a *Semaphore* are messages signal and wait. A signal is a notification by a *Process* to a *Semaphore* that it no longer needs its protection and corresponds roughly to turning a traffic light green.

When a process wants to gain access to a resource protected by a *Semaphore*, it sends the semaphore the wait message which is equivalent to attempting to proceed through and intersection and to turn the traffic light of the other street red. If the difference between signal and wait messages previously sent to the *Semaphore* is not positive, the sending *Process* is suspended until another process sends signal.

When several processes run, a deadlock can occur making it impossible for any of the processes to continue. As an example, a deadlock occurs when process X is suspended, and process Y waits for X to send signal to its *Semaphore*.

In the last section of this chapter, we extended our process-oriented example of train simulation with interactive control of the graphical layout. To simulate dragging of geometric objects, we monitored the mouse-moved event and repeatedly erased the object from its original position and redrew it in the new position. We used `invalidateRectangle: aRectangle repairNow: true` to obtain fast response without missed display operations. The same principle (erasing and redrawing) is the basis of all computer animations.

**Important classes introduced in this chapter**

Classes whose names are **boldfaced** are very important, classes whose names are printed in *italics*
are less important, classes whose names are printed in regular font are not of much interest.

**Process** - represents a thread of execution that monopolizes the CPU and other computer resources.

**ProcessScheduler** - class whose single instance *Processor* is in charge of scheduling processes. The basis of the whole operation of Smalltalk.
**Semaphore** - a process-synchronizing class used to restrict access to a shared resource. An analog of traffic lights.

**Widgets introduced in this chapter**

* slider - interactive graphical representation of a floating point number model.

**Terms introduced in this chapter**

* process - independent thread of execution that takes turns using the CPU and other computer resources with other processes; created from and executing a block

* process scheduler - object controlling the order in which processes are activated

* process priority - a number between 1 and 100 which determines relative priority of a process; the highest priority runable processes are executed first; 1 is the lowest process priority

* runnable process - a process ready to be executed and waiting for its turn

* semaphore - an object controlling activation of processes sharing a common resource; computer equivalent of traffic lights

* scheduling - controlling the order in which processes execute

* signal - message to a semaphore equivalent to changing a traffic light to green

* wait - message to a semaphore equivalent to attempting to pass an intersection and set the traffic light of the other street to red; can only be satisfied if the semaphore is currently “green”

* suspending a process - stopping the execution of a process and taking it out of the queue of runable processes without destroying it; can be reversed by resume

* resuming a process - returning a suspended process to its priority queue of runable processes

* terminating a process - terminating process execution and destroying it

* yielding a process - sending the currently active process to the end of its priority queue
**Abstract class.** A class that is never instantiated. Used to factor out properties shared by its subclasses. As an example, class Boolean is an abstract class with two concrete subclasses True and False.

**Abstract data type.**

**Abstraction.**

**Accelerator.**

**Action button.** Component of user interface looking like a button. Its activation by the mouse in Smalltalk sends a message.

**Algorithm.** An orderly sequence of steps describing the solution of a problem such as sorting a collection of names alphabetically or finding the largest of a set of numbers.

**Application.**

**Application model.** A class implementing the connection between the user interface (buttons, checkboxes, input fields, sliders, etc.) and the domain model consisting of objects that represent components of the problem domain. The user interface sends messages to the application model, which converts them to messages to specific objects in the domain model. The communication also works that way in the opposite direction. Example: *User interface* - buttons, sliders, and other widgets on the screen triggering and displaying deposits, withdrawals, account balances; *domain model* - objects representing accounts, transactions, and bank clients; application model - the object converting signals from the interface to messages to domain objects and vice versa.

**Argument.** An object sent as a parameter of a message. As an example, in message 3 + 17 object 3 is the receiver and object 17 is the argument. Message 5 between: 2 and: 17 has two arguments, objects 2 and 17.

**ASCII.** American Standard Code for Information Interchange. An internationally used code for representing printable and control characters as one-byte code. The most widely used representation of textual data.

**ASCII file.** File whose contents are to be interpreted as ASCII codes and thus displayable on a screen as text. Compare with *binary file*.

**Association.** A pair consisting of a 'keyword' and its 'value' as in a dictionary. The basic component of a *dictionary* structure.

**Binary file.** File whose contents are not to be interpreted as ASCII codes but rather as encoded data or instruction codes of an executable program. Consequently not displayable on a screen as text unless interpreted by a special program. Compare with *ASCII file*.

**Binary message.** A message composed of one or two special characters including ,+-@\ with a single argument as in 3 + 4 or in 3 @ 17.

**Binding**

**Block.** Short for *Block closure*.

**Block argument.** Variable declared inside a block as in [:index| array at: index]. Its scope is restricted to the block.

**Block closure.** One or more statements possibly preceded by block arguments, surrounded by square brackets as in [x sin], [x := rad sin. y := rad cos], [:x :y| Transcript show: x, y].

**BOSS.**

**Browser.** A multi-window Smalltalk tool providing access to source code of all declarations in the library. Used to examine existing code and to create and edit new code. Several browsers are provided ranging from a system wide system browser to browsers restricted to a specific class or method.

**Canvas.**

**Cascading.** A shorthand allowing sending a sequence of messages to the same receiver without repeating the receiver as in Transcript cr; show: 'abc'; cr instead of Transcript cr. Transcript show: 'abc'. Transcript cr.

**Category.** Grouping of related classes enforced by the *browser*. Helps to reduce the multitude of classes in the library into a more manageable set of categories, makes it possible to *file out* and *file in* a group of classes by a single command. Does not have any semantic meaning and moving a class from one category to another thus has no effect on its operation.

**Chaining.** Using the result of a statement as an argument or as the receiver of a message as in Transcript show: (3 factorial) printString where 3 factorial is the receiver of printString, and 3 factorial printString
is an argument of show: Makes code more compact, may save temporary variables, but makes code more
difficult to read and should not be overused.

**Changes file.**

**Character.** Usually refers to a symbol that can be displayed on the screen although some characters have only ‘control’ functions such as starting a new line.

**Check box.**

**Class.** A mold from which objects are created - a formal specification of an abstract template of which individual objects are instances. Contains the name of the class and its superclass, its variables, and methods. All instances of a class (objects created from its specification) share all variables and can execute all methods declared in the class and its superclasses.

**Class instance variable.** A variable declared with the 'class' button of the browser active, inherited by all subclasses, and accessible to all of their class and instance methods. Unlike a *class variable*, a class instance variable is distinct for each subclass that inherits it. Unlike class methods which are accessible to classes but not their instances, all types of class variables are accessible both to classes in which they are declared and their instances.

**Class method.** A method whose receiver must be the class in which the method is declared or its subclass.
Compare with *instance method*. Used mainly for creation of class instances (as in *Array new* or *Array new: 3*), for initialization of class variables (as in *Random initialize*), and for generally useful tasks that do not require the creation of an instance (as in *Dialog warn: 'This operation is illegal'*).

**Class variable.** A variable declared with the 'class' button of the browser active, inherited by all subclasses, and accessible to all of their class and instance methods. Unlike a *class instance variable*, a class instance variable is shared by the class in which it is declared and its subclasses; consequently, a change of its value by one class affects all other classes that share it. Unlike class methods which are accessible to classes but not their instances, all types of class variables are accessible both to classes in which they are declared and their instances.

**Clean block.** A block that does not depend on the context in which it is used. As an example, `[Dialog warn "Illegal operation"]` is clean while `[Dialog warn: warningMessage]` is not because it depends on the value of variable warning block declared and manipulated outside the block.

**Collection.** *Abstract class* holding all properties shared by concrete collections such as *Array*, *OrderedCollection*, and *Dictionary*.

**Compilation.** The process of converting the human readable source code to internal representation executable by the computer. In Smalltalk compilation occurs, for example, upon activation of the 'accept' command in the browser or the debugger or upon activation of 'do it' in the workspace. In the latter case, compilation is immediately followed by execution of the code, in the former case, the compiled code is only internally stored.

**Concatenation.**

**Concrete class.** A class declared with the intent to be used to create instances. As an example, class *Character* is a concrete class whose instances are widely used, mainly as elements of strings. See also *Abstract class*.

**Control statement.** Usually a composite statement that controls how its components are executed.
Examples: `ifTrue:`, `whileFalse:`, `do`: which select how many times their components are executed or which
of their components are executed.

**Controller.** In the Smalltalk *MVC* (model-view-controller) paradigm, that part of the user interface which monitors users input (keyboard and mouse) and communicates it to the model which then decides whether the action should cause a change in the displayed view, and notifies the view to change itself if necessary. Each active widget (button, input field, etc.) has a controller monitoring and processing its activation, a model to which it communicates all activity, and a view which takes care of redisplaying itself if requested to do so by the model.

**Data abstraction.**

**Data structure.** An established view and organization of data with attached access mechanisms such as an array, a set, or a dictionary. A composite object containing several components is also a form of a data structure.

**Dataset widget.** Similar to a table but used to display rows of objects with identical structure consisting of multiple components, such as rows of course marks for individual students.
**Decompilation.** The reverse of *compilation*. Converts compiled code to *source code*. Since compiled code does not contain information about variable names, decompiled code contains artificially created variable names instead of the original ones. Decompiled code may differ from source code because the compiler performs certain optimizations to improve the efficiency of execution.

**Debugger.** A multi-window Smalltalk tool allowing step-by-step execution, inspection of variables, and modification of source code and variable values. Used for debugging new code and for examining operation of existing code.

**Debugging.** Step-by-step execution performed to locate and correct mistakes (bugs) in a program.

**Declaration.** Formal specification of the name of a class and its parameters, its comment, or its methods. Must satisfy the syntactic and semantic rules of Smalltalk and is performed using a browser.

**Default.** Value to which an object is initialized when it is created. Normally `nil`, unless the initialization method explicitly initializes the object to a different value. As an example, button are initialized to display themselves with black text on gray background.

**Dependency.** A mechanism built into Smalltalk that allows mutually dependent objects to notify one another automatically when they change. Used by the *MVC paradigm*: When the *model* changes, it automatically notifies all its dependent *views* which then change their appearance if the change of the model requires it.

**Dictionary.** A set of *associations* - a collection of associations similar to a real life dictionary (but not sorted).

**Domain model.** That part of an application that represents the problem domain objects such as bank accounts, clients, deposits, withdrawals, and etc., in a banking application. The usually graphical appearance that the application presents to the user in the form of buttons, labels, etc. (the *user interface*), is connected to the domain model through the *application model*. Note that an application could represent the same domain model using several different user interfaces each requiring its own application model. Similarly, a given user interface could be used with several different domain models, each again requiring its own application model. In a narrower sense, each class representing a part of a problem domain, for example a class representing a bank account, is also called a *domain model*.

**Double dispatching.** Executing a message by sending it to the argument object, with the original receiver being used as argument. Used in arithmetic messages to simplify decision making and to make declaration of arithmetic messages more general. As an example, execution of `3 + 5.4` (message `+` with an integer receiver and a float argument) consists of sending message `5.4 sumFromInteger: 3` (message `sumFromInteger:` with a float receiver and an integer argument. Whereas the first form would require determining the type of the argument and executing appropriate form of addition, the second form does not require any tests because method `sumFromInteger:` is declared to deal with integer arguments.

**Distinguished instance.** Instance of a class that is intended to be unique. As an example, classes `True`, `False`, and `UndefinedObject` each have a single instance.

**Dynamic binding.** Languages using dynamic binding, such as Smalltalk, do not require the specification of the class to which an identifier denoting a variable or an argument must belong. This binding is performed when an object is assigned to the identifier during program execution. Main advantage: code may be very general because it may be executable with instances of many different classes. Disadvantage: Does not provide the extra degree of security provided in languages with *static typing* where the compiler can recognize improper use of variables even before the code is executed.

**Editor widget.** A widget that can display text on multiple lines and automatically adjust the contents of the lines to its current size. A writeable editor widget allows the user to cut, paste, edit, and perform similar operations, in the case of a code view also to execute code. When the execution ability is missing, the widget is usually referred to as a text editor.

**Encapsulation.** Bundling of the information held by an object and of its functionality into a single entity. Compare to procedural languages in which data is separated from functionality.

**Expression.**

**File.** Binary representation of data or code or a combination of both stored on a secondary storage device such as a disk or a CD ROM, under a user selected file name.

**File in.** The procedure of reading and automatically compiling and inserting into the library of a file containing the code of a method, a protocol, a class, or a category. The file must be in a special format produced by the *file out* command. The 'file in' command is available in file browsing tools.
**File out.** Command available in file browsing tools and used to store a method, a protocol, a class, or a category in a file, using a special form expected by the *file in* command. Used for transporting source code from one computer to another. The command is available in various Smalltalk browsers.

**Finalization.** Actions executed by the program when a window is being closed.

**Floating point number.** Internal computer representation of numbers with fractional components such as 3.14 or -0.00143. Compare to *integer*. In Smalltalk, represented by several different classes depending on magnitude and number of significant digits.

**Framework.**

**Global variable.** A variable accessible to any object and at any time, automatically saved when the Smalltalk environment is saved and automatically restored when Smalltalk is started up. Global variables are stored in the Smalltalk dictionary along with all other globally accessible objects including classes and pool dictionaries. This makes global variables dangerous because naming a global variable with the name of an existing class replaces the class with the global variable and destroys it.

**Graphical user interface (GUI) - the collection of windows, buttons, labels, and other widgets seen by the user of a computer application**

**Icon.** Visual representation of a collapsed window. In Smalltalk, the user can assign any image to the icon of a window.

**Image file.**

**Immediate object.** Object whose internal representation is not accessed by a pointer. In fact, the 'pointer' is the value of the object. Includes *SmallInteger* and *Character*.

**Indexable variable.** An instance variable or an object whose elements are accessed by index, as in an array.

**Information hiding.** The rule that internal variables of an object can only be accessed through methods explicitly declared for this purpose in the object's class. As an example, a point's x and y coordinates can be obtained and changed only because class Point contain declaration of messages to do this. Without these methods, the values of x and y would not be accessible.

**Inheritance.** The mechanism through which all variables and methods declared in a class are valid for all its subclasses as well. As an example, class *Collection* declares method *contents* and all its subclasses (*Array*, *Set*, *Dictionary*, etc.) thus also understand this message. Similarly, class *ControllerWithMenu* declares variable *menuHolder* and all its subclasses thus automatically inherit it too.

**Input field widget.** A one line text widget with editing capabilities such as cut, copy, and paste. May be writeable or read only.

**Inspector.** A Smalltalk tool opening a two-view window listing the components of the object being inspected in one subview, and the value of the selected coonent in the adjacent view.

**Instance.** Synonym of *object*. A realization of a class with specific values for each instance variable declared or inherited by the defining class. As an example, 3 and 5.1 are instances of class *SmallInteger* while individual labeled action buttons on a window are instances of class *ActionButton*.

**Instance method.** A method declared with the 'instance' button of the browser on. Instance methods can only be sent to instances of a class. Compare with *class methods* which can only be sent to the class itself but are not understood by instances.

**Instance variable.** Variable holding an object defining one of the parameters of an *instance* of a class.

Each instance of the same class has the same instance variables but each may have a different value.

Compare with *class variable* and *class instance variable*.

**Integer.** Internal representation of the mathematical concept of an integer, a number without a fractional point. In Smalltalk implemented by several classes for different ranges of magnitude.

**Interval.**

**Iteration.**

**Keyword**

**Keyword message**

**Label widget.**

**Launcher.**

**List widget.**

**Literal.**

**Loop.**

**Menu bar widget.**

**Menu button.**
Message.

Metaclass.

Method.

Model.

Mouse buttons.

Multiple inheritance.

MVC paradigm.

Object.

Object file.

Optimization.

Order of evaluation.

Ordered collection.

Overloading.

Palette.

Pane.

Parameter.

Persostent object.

Pointer.

Pool dictionary.

Po-up menu.

Polymorphism.

Private method.

Primitive method.

Private method.

Protocol.

Pseud variable.

Radio button.

Receiver.

Return object.

Reusability.

Selector.

self.

Semantics.

Set.

Shortcut key.

Signature.

Simulation.

Single inheritance.

Slider widget.

Source code.

Standard protocol names.

State.

State variable.

Statement.

Static binding.

Stream.

String.

Symbol.

Syntax.

Subclass.

Superclass.

super.

Temporary variable.

Text.

Text editor widget.
**Text file.**

**Transcript.**

**UI.**

**User interface.**

**Unary message.**

**Undeclared variable.**

**Value holder.**

**Variable.**

**View.**

**Widget.**

**Wildcard.**

**Window.**

**Workspace.**
## References

### Books

Kent Beck: Smalltalk: Best Practice Patterns, Prentice-Hall, 1997.

Timothy Budd: A Little Smalltalk, Addison-Wesley, 1987.

Erich Gamma, Richard Helm, Ralph Johnson, John Vlassides: Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1995.

Adele Goldberg: Smalltalk-80: The Interactive Programming Environment, Addison-Wesley, 1983.

Adele Goldberg, David Robson: Smalltalk-80: The Language and its Implementation, Addison-Wesley, 1985.

Adele Goldberg, David Robson: Smalltalk-80, The Language, Addison-Wesley, 1989.

Trevor Hopkins, Bernard Horan: Smalltalk: An Introduction to Application Development Using VisualWorks, Prentice-Hall, 1995.

Tim Howard: The Smalltalk Developer's Guide to Visual Works, SIGS Books, 1995.

Ted Kaehler, Dave Patterson: A Taste of Smalltalk, Norton, 1986.

Wilf Lalonde: Discovering Smalltalk, Addison-Wesley, 1994.

Wilf Lalonde, John R. Pugh: Inside Smalltalk, Volume I, II, Prentice-Hall, 1991.

Wilf Lalonde, John R. Pugh: Smalltalk/V, Practice and Experience, Prentice-Hall, 1994.

Simon Lewis: The Art and Science of Smalltalk, Prentice-Hall, 1995.

Chamond Liu: Smalltalk, Objects, and Design, Prentice-Hall, 1996.

Mark Lorenz: Rapid Software Development with Smalltalk, SIGS Books, 1995.

Lewis J. Pinson: An Introduction to Object-Oriented Programming and Smalltalk, Addison-Wesley, 1988.

Jonathan Pletzke: Advanced Smalltalk, Wiley, 1997.

Wolfgang Pree: Design Patterns for Object-Oriented Software Development, Addison-Wesley, 1994.

Timothy Ryan: Distributed Object Technology, Concepts and Applications, Prentice-Hall, 1996.

Dusko Savic: Object-Oriented Programming with Smalltalk, Prentice-Hall, 1990.

Susan Skublics, Edward J. Klimas, David A. Thomas: Smalltalk with Style, Prentice-Hall, 1996.

Dan Shafer, Dean A. Ritz: Practical Smalltalk, Springer-Verlag, 1991.

Dan Shafer, Scott Herndon: IBM Smalltalk Programming for Windows and OS/2, Prima, 1995.

David N. Smith: IBM Smalltalk: The Language, Benjamin Cummings, 1995.

### Periodicals

JOOP – Journal of Object-Oriented Programming, SIGS Publications

Object Magazine, SIGS Publications

Smalltalk Report, SIGS Publications

### Web and Internet

comp.lang.smalltalk – newsgroup

### Software
# Appendix 1 - Check Boxes, Radio Buttons, Input Fields, and their applications

## Overview

Check boxes are GUI widgets used to turn an option on or off. Radio buttons have a similar purpose but they are used to select one of many options. If the number of options is large, variable, or unknown, single or multiple selection lists are preferable to buttons and boxes.

Check boxes are used independently of one another. Each check box has its own *Aspect* variable which holds a Boolean value in a *ValueHolder* and this value determines whether the box is on or off. Radio boxes, on the other hand, are used as groups and the whole group shares a single *Aspect* variable holding a *Symbol* in a *ValueHolder*. Each radio button has its own special symbol and when the button is selected, this symbol is stored in the group's *Aspect* variable.

Input fields behave like one-line text editors except that the text in the field can be accepted not only by the *accept* command but also by pressing the <Enter> key. The accepted value is stored in the *Aspect* variable.

### A.1.1 Check boxes and radio buttons - an introduction

Built-in VisualWorks widgets include four kinds of buttons - action buttons, radio buttons, check boxes, and menu buttons. Action buttons are covered in Chapter 6 and we will now introduce check boxes and radio buttons (Figure A.1.1).

<figure><img src="image_257.png" /><figcaption>Figure A.1.1. Four built-in VisualWorks buttons - action button, check box, menu button, radio buttons.</figcaption></figure>

Before we start dealing with the technical aspects of the new buttons, we will first comment on their role in user interfaces. This is an important aspect of interface design because all widgets have their established uses and uncommon use may confuse the user. The conventional uses of buttons are as follows:

* Action buttons are used to send messages, radio buttons and check boxes are used to select options.

* Radio buttons are used in groups and their control is designed so that exactly one radio button is on at any time. In other words, radio buttons are used to make 1-of-n related but mutually exclusive choices. Radio buttons are suitable when the number of options is relatively small; when the number of choices gets large or when it is calculated at run time it is usually preferable to use scrollable single-selection lists. The purpose of radio buttons is similar to that of menus which have the advantage that they require less window space. On the other hand, radio buttons show all available choices at all times whereas menus display choices only when they are activated.

* Check boxes are used to make individual independent choices. When several check boxes are available, any number of them may be selected at the same time. In other words, check boxes are used
to make m-of-n choices. Check boxes are suitable when the number of choices is relatively small. For a large number of choices, it is usually better to use scrollable multiple-selection lists.

Although almost all applications use buttons in the way described above, these conventions are not cast in stone or enforced by software and may be violated if there is a good reason.

### Main lessons learned:

* GUI widgets are used according to established conventions. Ignoring these conventions may make the user interface difficult to use.

* Built-in VisualWorks buttons include action buttons, radio buttons, and check boxes.

* Action buttons are used to send messages.

* Radio buttons are used in groups to allow selection of one of several choices. When the number of choices gets large or when it is not fixed, use list widgets or menus instead.

* Check boxes are used in groups to make any number of simultaneous independent selections. When the number of choices gets large or when it is not fixed, use multiple-selection lists or menus.

### A.1.2 Check boxes

The aspect of a check box is a *ValueHolder* containing a *Boolean* object. Its value is true when the box is on, and false when the box is off. The default initial value is false (the default setting of the box is off) but this can be changed programmatically or with the Properties Tool. The value holder is the widget's model, and the widget is the value holder's dependent. The relationship between the model and the check box is bi-directional: Clicking the box changes the value of the model, changing the value of the model changes the visual form of the check box.

The name of the value holder's instance variable (and the name of the message that accesses it) is the *Aspect* of the check box and it must be specified in the Properties Tool (Figure A.1.2). The label and several additional properties are optional.

The definition of both the *Aspect* instance variable and the *Aspect* accessing method can be created automatically with the *Define* command and no further modifications of the *Aspect* method are required. As a point of style, we like to derive the name of the *Aspect* from the label, as in our illustration. This makes it easier to remember which *Aspect* method belongs to which check box.

<figure><img src="image_258.png" /></figure>
Figure A.1.2. The properties of a check box. If the label is specified as an image, the contents of the Label field must be the name of the message that returns the image that will be displayed next to the box.

### Example: Math table with check boxes

**Problem:** Design and implement an application with the user interface in Figure A.1.3. Clicking *Display* prints a table of values of mathematical functions selected by the check boxes; values of arguments range from 1 to 20 in steps of 1. Any number of functions may be selected simultaneously but when no check box is on, clicking *Display* does not have any effect. (This is an appropriate use of check boxes because the application allows any number of selections.)

<figure><img src="image_259.png" /><figcaption>Figure A.1.3. Example: Math table application.</figcaption></figure>

**Solution:** This simple application can be implemented as a single application model class and the only instance variables needed are those required by the check boxes. The work is done by the method activated by the *Display* button, and the corresponding method checks the current values of the value holders of all check boxes and produces the appropriate output to the Transcript.

**Implementation:** After painting the user interface and installing it on an application model, we defined the aspect methods and created the stubs using *Define*. To avoid confusion, we used the same names for button *Aspects* and for check box labels. The *Define* command created *Aspect* methods such as

**square**

<table><tr><td><code>^square isNil</code></td><td><code>ifTrue: [square := false asValue]</code></td></tr><tr><td></td><td><code>ifFalse: [square]</code></td></tr></table>

performing lazy initialization with false as the default value. If we wanted a check box to be initially on, we would have to initialize its *Aspect* variable in the initialization method to be a value holder on true, or specify that the box should be initially on in the Properties Tool.

The only remaining definition is that of method *display* sent by the action button. This method checks the values of the value holders of the check boxes and prints a table of the selected function values in the Transcript. Note that we use message value to extract the Boolean value from the *Aspect* variables:

**display**

"Check which boxes are on, calculate corresponding values, and display them in Transcript. Don't print anything if no box is selected."

(sin value or: [cos value or: [square value or: [cube value]]])

ifFalse: [^self].

"For all values in the range, calculate selected functions and print in Transcript."

Transcript clear.

sin value ifTrue: [Transcript show: 'sin'; tab].

cos value ifTrue: [Transcript show: 'cos'; tab].

cube value ifTrue: [Transcript show: 'cube'; tab].

square value ifTrue: [Transcript show: 'square'; cr].

1 to: 20 do: [:argument | "Examine all check boxes to determine which functions to print."

Transcript show: argument printString; tab.

sin value ifTrue: [Transcript show: argument sin printString; tab].

cos value ifTrue: [Transcript show: argument cos printString; tab].
cube value ifTrue: [Transcript show: (argument squared * argument) printString; tab].
square value ifTrue: [Transcript show: argument squared printString; cr]

The application works except for a small problem that occurs when you click *Display* and the *square* button is not selected. We leave it to you to identify and correct this minor problem.

### Main lessons learned:

* The *Aspect* of a check box is the name of an instance variable holding a Boolean *ValueHolder* representing the state of the box. It is also the name of the accessing method of this variable.

* The *Aspect* method and variable of a check box can be automatically defined with *Define* and the method does not require any modification if the box is initially off. Use the Properties Tool to turn the box initially on.

### Exercises

1. Implement the example from this section.

2. Our definition of *display* tests all check boxes on each pass and this is quite inefficient. Can you find a better solution?

#### A.1.3 Radio buttons

Radio buttons are always used in groups and exactly one radio button is always selected<fnref n="1" />. Because of this, all buttons in the group share one *Aspect* variable and its value identifies the button that is currently selected. This is done by assigning one *Selection* value to each button via the Property tool. *Selection* acts like a symbolic tag of the button and the value in the *Aspect* variable identifies the radio button that is currently on. Each radio button thus requires an *Aspect* variable and its accessing method (shared by all buttons in a group), and a *Selection* value (unique for each check box in a group). If the window contains several groups of radio buttons, the scope of *Selection* values is restricted to each group. As a consequence, the same *Selection* value may be used by different radio buttons if they are not in the same group (don't share the same *Aspect* variable).

##### Example: Controlling the case of a string

**Problem:** Design an application with the user interface in Figure A.1.4. Clicking *Enter text* opens a dialog asking the user to enter a string. Clicking *Display* prints the string in the Transcript using the style selected by the setting of the radio buttons as follows: When the *unchanged* radio button is on, the text is displayed unchanged, when the *capitalize* button is selected the text is displayed capitalized, when the *lower case* button is selected the text is displayed in lower case. (This is an appropriate use of radio buttons because exactly one selection must be made at any time.)

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

<footnote n="1">¹ If you don't initialize the *Aspect* value holder, the window will open with no radio button selected. This should normally be changed because it is inconsistent with the normal behavior of radio buttons.</footnote>
Figure A.1.4. Example: Radio buttons used to select one of three display styles.

**Solution:** The problem can again be implemented using just an application model class. We need one instance variable to hold the text entered by the user and one instance variable for the *Aspect* of the group; both the *Aspect* variable and its accessing method can be automatically created by *Define*.

We selected the name `#case` for the *Aspect* of the three radio buttons because its value determines how the text will be displayed. For the `Select` parameter of individual buttons, we chose `#unchanged`, `#capitalize`, and `#lowerCase` - names derived from button labels.

The accessing method automatically created by *Define* turns all radio buttons initially off. To turn the *capitalize* button on, we can initialize style to `#capitalize` as follows:

**initialize**

```
case := #capitalize asValue
```

Alternatively, if we defined a *case* accessing method by the *Definer*, it has an accessor with lazy initialization and we can then initialize the value with

**initialize**

```
self case value: #capitalize
```

We leave the method for the *Enter text* button to you as an exercise. It should open a dialog, prompt the user for a string, and save its value in an instance variable of the application model; we will call this variable *text*. The only remaining method is *display*. This method checks which radio button is on and displays the text in the Transcript using the selected style:

**display**

```
"Display text using selected style but leave initial text unchanged."
| newText |
"Calculate text using selected style."
newText := case == #unchanged
    ifTrue: [text]
    ifFalse: [case == #capitalize
                ifTrue: [text asUppercase]
                ifFalse: [text asLowercase]].
"Display in Transcript."
Transcript cr; show: newText
```

This seems perfectly reasonable - but it does not work! The text is always displayed in lower case, no matter which style we choose. Obviously, something must be wrong with the value of variable `newText`. And indeed - we made the typical mistake with value holders: The value of *case* is a *ValueHolder* - not a *Symbol* - and the value is 'inside' it. Expression

```
case == #unchanged
```

checks whether the variable holds a *Symbol*, which it does not. All checks thus fail and the last alternative of the nested messages is always executed, changing the text to lower case. For proper operation, we must check what is the *value* held in the *case* *ValueHolder*, not what is the value of *case* itself. The following version is correct:
### display

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

### Main lessons learned:

* Radio buttons are used in groups to select exactly one of several options.

* For each radio button, specify at least *Selection* and *Aspect*.

* The *Selection* value of a button is a *Symbol* assigned to the *Aspect* when the button is clicked. Each button in a group must have its own unique *Selection* value.

* The *Aspect* of a radio button is the name of an instance variable holding a *ValueHolder* on a *Symbol*; it is also the name of the accessing method of this variable.

* The value of the *Aspect* variable is the value of the *Selection* property of the currently selected button.

* The *Aspect* name must be identical for all radio buttons in a group.

* The *Selection* value of the radio button which should be on when the window first opens must be assigned as the value of a *ValueHolder* to the *Aspect* variable of the group in the *initialize* method.

### Exercises

1. Implement the example from this section.

### A.1.4 Input fields

An input field is essentially a one-line text editor complete with an `<operate>` menu. When set to read-only operation it can function as a program-controlled label.

Each input field has an *Aspect* variable containing a *ValueHolder* with a string. When the user enters text into the field and hits <Enter> or selects *accept* from the <operate> menu, the field stores its contents in its *Aspect* variable. Before the user accepts the contents of the text field in this way, the text displayed in the field and the text stored in its *Aspect* variable may be different and the text field widget itself thus has another instance variable which holds the displayed text (Figure A.1.5). In this respect, the input field is again similar to the text editor.

<figure><img src="image_262.png" /><figcaption>Figure A.1.5. The displayed and the accepted text may be different and are held in two distinct variables.</figcaption></figure>

**Example 1:** Read-write input field connected to a read-only field
**Problem:** Create a window with two input fields as in Figure A.1.6. The top field is for input and the bottom field is for output. When the user enters text into the top field and *accepts* it, the text is displayed in the bottom field. The bottom field is a read only field (and the name *input field* is thus a misnomer).

<figure><img src="image_263.png" /><figcaption>Figure A.1.6. Example: Accepted changes in the top field are displayed in the read-only field below.</figcaption></figure>

**Solution:** Paint the widgets and specify their *Aspects* (we chose `inputField` for the top field and `outputField` for the bottom field), select `Read Only` as the special property of the bottom field. Install the canvas and use the `Define` command to create the *Aspect* variables and methods of both fields. Both methods perform lazy evaluation, assigning

### String new asValue

to *Aspect* variables when first accessed. You can now open the application and check that you can type into the top field but not into the bottom field. Of course, typing into the top field does not have any effect on the bottom field because we have not defined any mechanism for linking the two fields together.

The implementation of the desired behavior will be as follows: When the user *accepts* new text in the input field and thus changes the value of variable `inputField`, the change of `inputField` will send message `newInput` to `outputField`; this message will send the value: message to `outputField` and change its value. This, in turn, will change the text displayed in the output field because the output field widget is a dependent of the `outputField` variable. In plain English, when the user tells `inputField` 'change your value', `inputField` will tell `outputField` 'change your value'; since the output field widget is a dependent of `outputField`, this will say 'redisplay yourself with the new text' to the `outputField` widget (Figure A.1.7).

<figure><img src="image_264.png" /><figcaption>Figure A.1.7. Desired link between the two text fields. Full lines represent built-in behavior, interrupted line is behavior that must be defined.</figcaption></figure>

### To set this mechanism up, we must

1. inform the `inputField` value holder that when its value changes, it must send message `newInput` to the application model.
2. write method `newInput`.

To implement Item 1, we must send `onChangeSend:` to: to the model of the widget in the `initialize` method<fnref n="2" />:

**initialize**

`inputField ChangeSend: #newInput to: self`

Unfortunately, this does not work and we get the exception in Figure A.1.8 even before the window opens.

<figure><img src="image_265.png" /><figcaption>Figure A.1.8. Error notifier obtained when trying to open the example application.</figcaption></figure>

We don't even need to open the debugger to find the reason for this problem - the cause is clear from the notifier which says that “while executing method `initialize`, our application model sends message `onChangeSend:` to: an `UndefinedObject`. Why `UndefinedObject`? In the definition of `initialize`, we are sending `onChangeSend:` to: `inputField` but `inputField` is still `nil`. To make `inputField` a `ValueHolder` on the string in the input field widget, we must first assign a `ValueHolder` object to `inputField`:

**initialize**

`inputField := " asValue. "This value will be displayed when the window opens."`
`inputField ChangeSend: #newInput to: self`

With this modification, the window opens properly and whenever the user *accepts* new text in the input field, `inputField` sends `newInput` to `self` - the application model.

We have now established the 'link' and to complete the program, we must write the `newInput` method. When this method is invoked it should simply get the new text (the value of `inputField`) and assign it to the value of `outputField`. The definition is as follows:

**newInput**

`outputField value: inputField value`

The example is now fully operational.

**The mechanism behind `onChangeSend:`:**

<footnote n="2">² Alternatively, we could specify `#newInput` as the *Action on changed* of the widget in the Notification property in UI Painter as explained in Appendix 8.</footnote>
We have seen that the result of an expression such as

`aValueHolder ONCHANGE: aMessage to: aReceiver`

is that whenever `aValueHolder` gets the value: message (for example by a mechanism built into the input widget), it sends `aMessage` to `aReceiver`. To see how this works, we examine the definition of `ONCHANGESEND: to: in class ValueModel` and find

**ONCHANGESEND: aSymbol to: anObject**

"Arrange to receive a message with aSymbol when the value aspect changes on anObject."

<table><tr><td>self</td><td>expressInterestIn: #value</td></tr><tr><td></td><td>for: anObject</td></tr><tr><td></td><td>sendBack: aSymbol</td></tr></table>

where the definition of `expressInterestIn:for:sendBack: in class Object` is

**expressInterestIn: anAspect for: anObject sendBack: aSelector**

"Arrange to receive a message with aSelector when anAspect changes at anObject"

<table><tr><td>| dt |</td></tr><tr><td>dt := DependencyTransformer new.</td></tr><tr><td>dt</td><td>setReceiver: anObject<br/>aspect: anAspect<br/>selector: aSelector.</td></tr><tr><td>self addDependent: dt</td></tr></table>

This shows that

`aValueHolder ONCHANGE: aMessage to: aReceiver`

creates a DependencyTransformer and adds it to the dependents of `aValueHolder`. As a consequence, when `aValueHolder` gets value:., it tells this new dependent about it.

What is a DependencyTransformer and what does it do when it is notified by its model `ValueHolder`? When you examine DependencyTransformer, you will find that it keeps the selector of a message (aSelector in the definition above) and a pointer to another object (anObject). When it receives message update: with argument anAspect, it sends message aSelector to anObject. In summary, the `ONCHANGESEND: to:` sets up a new dependent of the value holder, and this new dependent fires its assigned message to its assigned receiver whenever asked to update itself (Figure A.1.9). Essentially, a DependencyTransformer's is a translator that transforms the update: message into another message.

<figure><img src="image_266.png" /><figcaption>Figure A.1.90. Events triggered by sending value: to a ValueHolder with a dependent DependencyTransformer.</figcaption></figure>
## Main lessons learned:

* An input field is a one-line text editor.

* An input field has only one essential property - its *Aspect*. The *Aspect* is the name of an instance variable holding a *ValueHolder* on the accepted text, and the name of its accessing method.

* To display text when the window opens, assign a *ValueHolder* with this text to the *Aspect* variable in the *initialize* method.

* To store the text in an input field to the *Aspect* variable, the user must press <Enter> or execute *accept* from the field's <operate> menu.

* Since the accepted value and the displayed value may be different, the displayed value is held in an instance variable of the input field; the accepted value is held in the *Aspect* variable in the application model.

* An input field may be defined as a read-only widget. This means that the user cannot type into it and that the field is insensitive to mouse button clicks, making it impossible to give it a menu.

* To change the text displayed in an input field programmatically, send value: to its *Aspect* variable.

* To force a variable holding a *ValueHolder* to send a message whenever its value changes, send it the `ONCHANGESEND`: aMessage to: anObject message. anObject is normally self because aMessage is usually defined in the application model.

* The `ONCHANGESEND`: aMessage to: aReceiver message is the basis for setting up links between widgets.

* The object that transforms the change of a value holder into a message to an object is an instance of *DependencyTransformer*.

## Exercises

1. Modify our example 1 to display 'Input text' in the input field and 'Output text' in the output field when the window first opens. Note that once you do this, you don't need lazy evaluation for this variable any more.

2. Modify our example as follows: Change the type of input/output to numeric, center the text in the field, change the color of the input field text to blue and that of the output field to red.

3. Write a short description of *DependencyTransformer*.

4. Trace the behavior of the *DependencyTransformer* by including a self halt into the `newInput` method. Write a description of your findings.

5. Enact a typical scenario for the input field - output field example.

### A.1.5 A computerized restaurant menu

In this section, we will design and implement a simple application using check boxes and an input field - a computerized restaurant menu that allows the user to choose meals by clicking buttons (Figure A.1.10). When the user selects or deselects an item, the menu immediately updates the current total at the bottom of the window. When the user presses the OK button, a window opens saying that the order is being processed. Check boxes for selection of pizza toppings are enabled only when the *Basic* pizza check box is on.
<figure><img src="image_267.png" /><figcaption>Figure A.1.10. Computerized restaurant menu.</figcaption></figure>

**Design:** Although the problem could be a part of a large application that keeps track of bills, supplies, and other things, we will treat it as an exercise in UI design and implement it with a single application model class. Aspect methods of individual check boxes and the text field will be created automatically, the *Total* will be a read-only field with centered output, and the *OK* button will require a method that will open the confirmation window. An initialization method will set up the dependencies.

**Implementation:** Painting and installing the interface and defining Aspects is, in general, quite routine except that the value in the input field is a number and should be displayed with two decimal digits (as dollars and cents). Although input fields display strings, other kinds of objects such as numbers and dates are also frequently required and the text field widget can convert them to and from strings automatically. In our case, we select the *fixed point* format in the Properties Tool window. We also select *centered* format.

The next step is an initialization method defining mainly how the application model responds to state changes of individual check boxes. As we know, registering interest in changes is achieved by the `onChangeSend:` message and this requires that we make the value of each *Aspect* variable a *ValueHolder*. Since we have 13 check boxes, this will require 13 false `asValue` messages followed by 13 `onChangeSend:` messages. This would make the definition much longer than the recommended method size (as a rule of thumb, method definitions should not be longer than the browser's text field) and we will thus divide it into the variable initialization part and the change specification part. Each part will be implemented by a separate method:
initialize

self initializeVariables.

self initializeChanges

The definition of initializeVariables is

initializeVariables

"Set check box Aspect variables as value holders on false to be able to send them ChangeSend to:
during the next step of initialization, and to set all check boxes off."

appleJuice := false asValue.

applePie := false asValue.

basic := false asValue.

brownies := false asValue.

chicken := false asValue.

coke := false asValue.

crepes := false asValue.

figs := false asValue.

gazpacho := false asValue.

halibut := false asValue.

lentil := false asValue.

mozzarella := false asValue.

pineapple := false asValue.

total := 0.0 asValue

"To display 0.0 for total when the window opens"

and method initializeChanges is

initializeChanges

"Specify change messages to be sent on changes of value holder variables"

"Each change message will check the state of the value holder and update the total."

appleJuice ChangeSend: #checkAppleJuice to: self.

applePie onChangeSend: #checkApplePie to: self.

basic onChangeSend: #checkBasic to: self.

brownies onChangeSend: #checkBrownies to: self.

chicken onChangeSend: #checkChicken to: self.

coke onChangeSend: #checkCoke to: self.

crepes onChangeSend: #checkCrepes to: self.

figs onChangeSend: #checkFigs to: self.

gazpacho onChangeSend: #checkGazpacho to: self.

halibut onChangeSend: #checkHalibut to: self.

lentil onChangeSend: #checkLentil to: self.

mozzarella onChangeSend: #checkMozarella to: self.

pineapple onChangeSend: #checkPineapple to: self

This does not appear too intelligent because both methods contain a long sequence of essentially
identical messages. We will examine whether there are better solutions in the next section.

The *Action* method of the OK button is trivial - it simply opens a Dialog box - and we leave it to you as an exercise. The *Aspect* methods of the check boxes created by *Define* should be created with *initialization* off (we already initialized all *Aspect* variables) and the only methods that require attention are the check messages in *initializeChanges*. Most of them will be defined along the following pattern:

checkAppleJuice

"The apple juice box has just changed its state. If it has been clicked on, add the price of the item to total, if it has been clicked off, subtract the price from the total."

appleJuice value

ifTrue: [total value: (total value + 0.70)]

ifFalse: [total value: (total value - 0.70)]
The logic of the definition captures the fact that the method is executed for every change of the state of the check box - when the box is clicked on as well as when it is clicked off. Note that we use value: to set the new total in order to propagate the change to the input field widget.

The only change method that is different is the method for the Basic Pizza check box. This method must perform the following tasks:

* If the box is clicked on, it must change the value of the total and enable the toppings buttons.

* If the box is clicked off, it must disable the toppings buttons and subtract the price of the pizza and the price of any toppings that have been on from the total.

To implement this behavior, we must know how to enable and disable a widget. The principle is that if you give a widget an ID, you can access it at run time via the UI builder, for example to enable or disable it (messages enable and disable) or to hide or show it (be invisible and be visible). An ID is assigned via the Properties tool as in Figure A.1.11.

<figure><img src="image_268.png" /><figcaption>Figure A.1.11. Toppings boxes must have IDs so that the program can enable and disable them.</figcaption></figure>

We have just established the principle of the logic of method checkBasic. The details are as follows:

* If Basic box is on then
  add basic price to total
  enable toppings boxes

* If Basic box is off then
  disable toppings boxes
  subtract basic price from total
  change the value of those toppings boxes that are on to off using the value: message
  (The corresponding value holders will send their change messages which will
  turn toppings boxes off and subtract their price from total)

From this specification, we can now easily write the definition:

### checkBasic

"The Basic box has just changed, recalculate the total and modify the display"
basic value

if True: "Box was just clicked on - enable toppings boxes, add price of basic pizza to total."
[total value: total value + 3.50.
(builder componentAt: #mozzarella) enable.

(componentAt: #figs) enable.

(builder componentAt: #pineapple) enable.

(builder componentAt: #mozzarellaPrice) enable.

(builder componentAt: #figsPrice) enable.

(builder componentAt: #pineapplePrice) enable]

ifFalse: "Box was just clicked of - disable toppings boxes, subtract price of basic pizza from total."

[(builder componentAt: #mozzarella) disable.

(builder componentAt: #figs) disable.

(builder componentAt: #pineapple) disable.

(builder componentAt: #figsPrice) disable.

(builder componentAt: #pineapplePrice) disable.

total value: total value - 3.50.

"Subtract price of selected toppings from total."

mozzarella value ifTrue: [mozzarella value: false].

figs value ifTrue: [figs value: false].

pineapple value ifTrue: [pineapple value: false]]

This definition shows how to communicate with widgets at run time: To obtain a widget<fnref n="3" />, ask the builder using componentAt: ID; then send the appropriate message.

## How widget IDs work

The basis of the operation of IDs is method componentAt which is defined in class UIBuilder as follows:

### componentAt: aKey

"Retrieve the SpecWrapper of the indicated component."

^namedComponents at: aKey ifAbsent: [nil]

This definition shows that to the builder gets a widget's wrapper by asking its instance variable namedComponents for the component at the given ID. namedComponents holds a registry of ID -> widget wrapper pairs and we encourage you to examine it with an inspector.

## Main lessons learned:

* Any GUI widget may have an ID, an instance of Symbol. Widget IDs must be unique within an application model or more accurately within the scope of a UI builder.

* An ID is required only for direct communication between the application and the widget, for example to enable, disable, show, or hide it.

* The builder holds a registry of widget IDs. To obtain a widget (or rather its wrapper), request it via its ID from the builder using the componentAt: id message. The builder itself is an instance variable of the application model.

* A method definition should not exceed the size of the browser's code view by much. If it does, try to find a more compact solution or split the method into several shorter methods. There are, of course, justifiable exceptions to this rule.

## Exercises

1. Complete the Restaurant Menu application and test it. You will have to learn how to use the region widget to draw the rectangles around the menu. Make the rectangles blue with a red outline, display the names of the courses such as Soup and Pizza in red, and the rest in black.

2. Equip the window with a vertical scroll bar to provide more space for courses.

<footnote n="3">³ In reality, the builder does not return the widget itself but the 'wrapper' around it but this distinction is unimportant at this point.</footnote>
3. Implement meal names with read-only input fields with no borders instead of labels. What are the relative advantages of the two implementations?

4. Browse class UlBuilder, read its comment, and examine its *examples* class protocol. These example methods show how to create a builder and a user interface programmatically instead of using UI painter.

5. Insert a breakpoint into checkBasic to inspect the components of the builder at run time.

### A.1.6 Other implementations of Restaurant Menu

When we introduced the `initialize` method in the previous section, we noted that both of its constituent messages are awkward because they contain too much repetitive code. As an example,

**initializeVariables**

```
appleJuice := false asValue.
applePie := false asValue.
basic := false asValue.
brownies := false asValue.
chicken := false asValue.
coke := false asValue.
crepes := false asValue.
figs := false asValue.
gazpacho := false asValue.
halibut := false asValue.
lentil := false asValue.
mozzarella := false asValue.
pineapple := false asValue.
total := 0.0 asValue
```

consists of a sequence of identical assignments to different variables. One would think that it should be possible to rewrite it more compactly, for example as

**initializeVariables**

“Initialize all Aspect variables as value holders on false to set all check boxes initially off.”

```
appleJuice applePie basic brownies chicken coke crepes figs gazpacho halibut lentil mozzarella false asValue

total := 0.0 asValue "To display 0.0 for total when the window opens"
```

Although this solution is legal, it is incorrect because it assigns the same value holder to all *Aspect* variables. As it is, changing the state of any check box will thus change all others (Figure A.1.12).

<figure><img src="image_269.png" /><figcaption>Figure A.1.12. Assigning the same *ValueHolder* to all *Aspect* variables locks all check boxes together.</figcaption></figure>

We must assign a different value holder to each variable (Figure A.1.13) along the following lines:

**initializeVariables**
"Initialize all Aspect variables as value holders on false to turn all check boxes off."

(appleJuice applePie basic brownies chicken coke crepes etc.) do:

[:variable | variable := false asValue].

total := 0.0 asValue

"To display 0.0 for total when the window opens"

<figure><img src="image_270.png" /><figcaption>Figure A.1.13. Each check box must have its own ValueHolder.</figcaption></figure>

This formulation will not work either because the literal array is an array of Symbols and consequently the value of the block variable *variable* is a Symbol. This is unacceptable because the left hand side of an assignment must be a variable name. Since aspect variables are necessary and assignment to a variable cannot be avoided, it seems that we cannot simplify the *initializeVariables* method. But what about the *initializeChanges* method?

To find a working solution, we must return to the origin of our problem and consider what we are trying to do in *initializeChanges*. Our ultimate goal is to send *onChangeSend:to*: to the value holders associated with the individual check boxes. In other words, the point is not to communicate with the *variables* but to use them to access the *value holders*. If there is some other way to access the value holders directly, we don't need to bother with the *variables*. And if we don't have to access the *variables*, then there may be an easier way.

It turns out that in our case there are two ways to access the value holders directly - one through their accessing methods and one through the builder. We will now formulate a new solution using both approaches.

### Solution 1: Using the builder to access a widget's value holder

To access the value holder of a widget through the UI builder requires an understanding of the application opening process. From the perspective of our current interest, this process works as follows:

1. When the application model class gets the open message or its equivalent, it creates an instance of a `UIBuilder` with, among other things, variable bindings containing an `IdentityDictionary`.

2. The builder reads the specification of the interface (in our case stored in `windowSpec`), extracts the description of each widget, and executes the following steps if the widget has an *Aspect* method:

i. It sends the component's *Aspect* message to the application model, expecting to get the value of the widget's *Aspect* variable, a `ValueHolder`.

ii. It adds the pair

(*Aspect* name as Symbol) -> *ValueHolder* to the bindings dictionary.

iii. It makes the corresponding widget a dependent of the `ValueHolder` (Figure A.1.14).

<figure><img src="image_271.png" /></figure>
<figure><img src="image_272.png" /><figcaption>Figure A.1.14. Builder's bindings dictionary.</figcaption></figure>

Once the bindings dictionary exists, we can access its values (the value holders) by sending message `aspectAt: aSymbol` to the builder. As an example, `aspectAt: #basic` returns the value holder of the Basic check box.

We conclude that if we leave the `ondaChangeSend:to:` message until *after* the builder is finished building the interface, we can remove the `initializeChanges` method and access the value holders via the builder instead of going through the variables as in

**postBuildWith: aBuilder**

"Send onondaChangeSend:to: to each aspect value holder."
(aBuilder aspectAt: #appleJuice) onondaChangeSend: #checkAppleJuice to: self.
(aBuilder aspectAt: #applePie) onondaChangeSend: #checkApplePie to: self.
etc.

This definition does not look any simpler than `initializeChanges` but it can be simplified: We can now put all *Aspect Symbols* into an array, put the corresponding change message symbols in another array so that names of *Aspect* symbols parallel symbols of their corresponding change messages (Figure A.1.15), and all messages in a single enumeration statement.

<figure><img src="image_273.png" /><figcaption>Figure A.1.15. Parallel arrays of variables as symbols and their corresponding change messages.</figcaption></figure>

The definition can now be written as follows:

**postBuildWith: aBuilder**

"Send onondaChangeSend:to: to each aspect value holder."
aspectSymbols := #(#appleJuice #applePie #basic #brownies etc.).
changeSymbols := #(#checkAppleJuice #checkApplePie #checkBasic #checkBrownies etc.).
aspectSymbols with: changeSymbols do[ :aspectSymbol :changeSymbol]
    (builder at: aspectSymbol) onondaChangeSend: changeSymbol to: self]

**Solution 2: Accessing value holders via their accessing methods**

Another way to register change messages is as follows: Since we have *accessing methods* for the value holders, we can put their names in an array as *Symbols*, and execute them using enumeration and perform:, obtaining the value holders. The principle is that an expression such as

`self perform: #appleJuice`

executes
self appleJuice

and returns the value holder for the *Apple Juice* check box. We can then send `ONCHANGESEND:` to this value holder as in

`(self perform: #appleJuice) ONCHANGESEND: #checkAppleJuice to: self`

The corresponding definition is

**postBuildWith: aBuilder**

```
"Send ONCHANGESEND: to: to each aspect value holder."
aspectMethods := #(#appleJuice #applePie #basic #brownies etc.).
changeMethods := #(#checkAppleJuice #checkApplePie #checkBasic #checkBrownies etc.).
aspectMethods with: changeMethods do[ :aspectMethod :changeMethod]
    (self perform: aspectMethod) ONCHANGESEND: changeMethod to: self]
```

Several notes are in order:

* If we have object-accessing methods, we can use this approach in any situation where we need to access a collection of objects in a uniform way.

* With this approach, we don't have to send `ONCHANGESEND` assignment in `postBuild:`, it will work equally well in `initialize` because of the operation of *Aspect* methods: When the builder builds the bindings dictionary, it sends the *Aspect* message and if the *Aspect* variables already contain value holders, the accessing message returns the value holder unchanged. The interface building process thus will not disrupt the bindings and the `ONCHANGESEND` message assignments built by our code.

The last note has a very important flip side: When using *Aspect* variables, one must be careful not to affect the bindings built by the builder. As an example, assume that we want to open our window with all the check boxes on. This requires that the values of the *Aspect* objects be value holders on `true` and this could be achieved for example by

**postBuildWith: aBuilder**

```
...
#(#appleJuice #applePie basic etc.) do:
    [ :aspectSymbol | (builder at: aspectSymbol) value: true].
...
```

It is tempting to write

**postBuildWith: aBuilder**

```
...
#(appleJuice applePie basic etc.) do:
    [ :aspectSymbol | (builder at: aspectSymbol put: true asValue].
...
```

but this is wrong. The reason is that when the builder constructs the bindings, it makes each check box a dependent of a particular *ValueHolder*. Sending `value:` to this value holder changes its value but leaves the model→dependent binding between the value holder and the widget unchanged.

If we used `at:put:` instead of `value:`, the builder would replace the existent *ValueHolder* with a new *ValueHolder* and since a new value holder does not have any dependents, the dependency between the value holder and the widget would be broken. Future changes to the value holder and changes to the state of the widget would thus be independent of one another (Figure A.1.16). This mistake is quite common and leads to problems that are not easy to trace.

new
value holder
<figure><img src="image_274.png" /><figcaption>Figure A.1.16. Effect of builder at: applePie put: true asValue (left) and (applePie at: symbol) value: true (right). Since the original value holder on the left is eliminated from the bindings dictionary and garbage collected, unless other references to it exist.</figcaption></figure>

### Another improvement: Updating total by a single method

The use of one total-updating message for each check box as in

#### checkAppleJuice

appleJuice value

ifTrue: [total value: (total value + 0.70)]

ifFalse: [total value: (total value - 0.70)]

seems redundant because most of the check box total-updating messages are almost identical. Another way to solve the problem is to define a single method handling all updates (other than the pizza group which is different) and send it when any value holder changes. The method will go through all value holders, check their state, and recalculate the total as follows:

#### updateTotal

| newTotal prices values |

"Check all value holders and update the total."

values := #(appleJuice applePie etc.).

prices := #(0.70 3.70 etc.).

newTotal := 0.

values with: prices do: [ :id :price | (builder at: id) value "If the box is on, add item's price."

ifTrue: [ newTotal := newTotal + price]].

total value: newTotal

With this method, we can now change all check methods to the following format:
### checkAppleJuice

```self updateTotal```

Considering that we must create the values and prices arrays every time when we execute `updateTotal`, it will be better to store values and prices in two new instance variables called `values` and `prices` and initialize them to the two arrays shown above once and for all. The complete solution is now as follows:

```applicationModel subclass: #DriveIn```

```instanceVariableNames: 'prices values etc.'``` etc.

### initialize

```values := #(*appleJuice applePie etc.).``` prices := #(*0.70 3.70 etc.). etc.

### postBuildWith: aBuilder

```values do: [:id | (builder at: id) ONCHANGE send: updateTotal to: self]```

### updateTotal

```| newTotal prices values |``` "Check all value holders and update the total."

```newTotal := 0.```

```values with: prices do: [ :id :price | (builder at: id) value "If the box is on, add item's price." ifTrue: [ newTotal := newTotal + price]].```

```total value: newTotal```

and

### checkAppleJuice

```self updateTotal```

and similarly for all other check methods.

In this solution, we are doing many more calculations but the solution is much simpler. Since the number of calculations is still very small and their nature trivial, this solution is better.

### Main lessons learned:

* While building the user interface, `UIBuilder` constructs a dictionary of bindings containing `Aspect` Symbols as keys and their value holders as values. To obtain a value holder, it sends the `Aspect` message defined as the widget's `Property` to the application model. It then registers the widget's wrapper as the value holder's dependent.

* Accessing values of instance variables by enumeration can be simplified by defining an accessing method for each of them and enumerating over an array of `Symbols` corresponding to the selectors of these accessing messages.

### Exercises

1. Complete the application.

2. Since all check methods do exactly the same thing if we used the `updateTotal` method, it does not seem that we need them after all. Modify the implementation accordingly.
### A.1.7 Validation of user input

The logic of an application often requires certain checks and actions when the user enters new data into an input field, double clicks an entry in a list widget, or triggers another input event. Validation and Notification properties available for certain widgets provide this facility and we will now show a simple example of their use.

**Example: Validating user input**

**Problem:** Modify Example 1 from Section A.1.4 - entering text into an input field - to prevent the user from entering and accepting digits.

**Solution:** This problem is a pure extension of Example 1 and we will implement it as a subclass of its solution. Before we do, however, let's explore the validation features available in VisualWorks.

For several widgets, including input field, the Properties Tool contains two special pages of additional properties called Validation and Notification (Figure A.1.17). According to User's Guide, 'validation properties are specified when you want a widget to ask its application model for permission to proceed with certain actions, namely, accepting focus, changing internal state, or giving up focus.' Validation message must return true for 'proceed' and false for 'ignore'. Notification, on the other hand, is used to inform the application model that one of the three events listed above has occurred. The message specified as a notification property is automatically sent to the application model when the event occurs.

<figure><img src="image_275.png" /><figcaption>Figure A.1.17. Validation properties of input fields.</figcaption></figure>

As an example, if the method specified as the widget's Exit property returns true, the new text is accepted but if it returns false, the new value is not accepted. In our example, we specified validate as the name of the Exit method. If we defined validate as

**validate**

"Accept new value under all conditions."

^true

the new value would always be accepted. If we defined validate as

**validate**

"Ignore new value under all conditions."

^false
the new value would always be ignored. In our problem, we are to check the input when the user attempts to accept it, and accept it only if all the characters are letters. To do this, validate must obtain the text entered (and displayed) in the input field and test whether all its characters are letters.

To obtain the text displayed in an input field, we cannot go to the *Aspect* value holder of the widget because the text has not yet been accepted. Instead, we must get the widget from the builder and extract the text directly from it. To be able to access the widget, we must give it an ID (we called it `#inputField`) and ask the builder for this component. The rest, by trial and error if you don't know any better, is to ask the component for the widget ('component' is the wrapper around it), get the widget's controller, get the view which holds and displays the text, and then get the contents. Altogether, we can get the string displayed in the input field (whether accepted or not) by sending

(builder componentAt: #inputField) widget controller view displayContents string

After getting the string, we can check whether the string contains a digit. If the answer is true, we want to accept the string and proceed. If the answer is false, we want to ignore the input. The following implementation uses this principle:

**validate**

"Accept the input if it consists of letters only."

`| string |`

`string := (builder componentAt: #inputField) widget controller view displayContents string.`

`^string contains: [:char | char isDigit ] not`

This is only an introduction to validation features available in VisualWorks. We leave it to you to explore additional details of Validation and Notification in exercises.

**Main lessons learned:**

* Several VisualWorks widgets, including input field, provide validation of user input.

**Exercises**

1. Is it possible to implement our example without validation?

2. Write an application to test the exact behavior of Notification and Validation. The user interface will consist of one input field and one check box, each with all Validation and Notification properties. Each of the Validation methods will open a confirmation dialog informing the user about the type of event that occurred and allowing him or her to return true or false as the answer. Notification methods will simply open an appropriate 'warning'.

### A.1.8 A Course Evaluation program

As an illustration of the use of radio buttons, we will now design and implement another simple application whose purpose is to computerize course evaluation forms.

*Specification:* The user opens the application by executing a Smalltalk expression containing the name of the course. When the application opens, the user can complete the form by clicking radio buttons associated with individual questions (Figure A.1.18). Exactly one answer must be selected for each question and the initial selections when the window opens are *N/A* (for 'not applicable'). The student can also add an optional comment at the bottom of the form. When finished, the student clicks the *Print and close* button and a summary of the data on the form is printed in the Transcript.
<figure><img src="image_276.png" /><figcaption>Figure A.1.18. Computerized Course Evaluation form.</figcaption></figure>

Using radio buttons in this problem may seem a bit unusual because we said that radio buttons should be used only when there are only a few choices and this seems hardly the case here. In fact, this guideline is still satisfied because we have a relatively small number of buttons for each question and the number of choices is thus always limited.

*Design:* As it is, the form simply collects information and does not perform any processing. Consequently, we will implement it as a single application model class called `CourseEvalForm`. The full list of its responsibilities is as follows:

* Allow the user to specify the name of the course when opening the application.

* Provide user interface for entering data.

* When the user clicks *Print and close*, close the window, gather the information into a suitable form, and print it in the Transcript window.

These responsibilities will be implemented by an opening method (specifying course number as an argument), an initialization method (to set up initial states of radio buttons), a set of *Aspect* methods (one for each row of radio buttons), an *Aspect* method for the comment, and an *Action* method for the *Print and close* button. We will gather the answers to the 13 questions in a 13-element array, and define an instance variable to hold the comment.
*Implementation:* The painting of the user interface and defining the properties is routine but we saved some time by creating one row of buttons and copying it for each additional row. The *Aspect* of all buttons in the first row is identical - `#quest1`, the *Aspect* of all buttons in the second row will be `#quest2`, and so on.

For the *Select* property of individual buttons we chose #0 for the *Select* value of the leftmost button because this radio button corresponds to choice 0, #1 for the next button, and so on. The *Select* value of the *N/A* button in the last column will be #n/a. All buttons in one column will have the same *Select* value but this is acceptable: Although *Select* must be different for each button in a *group*, it may be repeated in different groups. The *Aspect* of the comment text field will be called *comment*. The *Aspect* variable of the *course name* read-only field at the top of the form will be *courseNumber*.

After painting the interface, installing it, and using *Define* to define the instance variables and their associated methods, we can now define the remaining instance variables and implement the methods. The 13-element array for answers will be called *answers*. All accessing methods of the radio buttons have already been created by *Define* and we don't need to change them. For the class method that opens the application, we cannot use the *open* method because the user must be able to specify the course name. We will thus create a specialized opening method called *openOnCourse*: aString with course name as its argument, to be used as in

CourseEvalForm openOnCourse: 'COMP 1003'

This method must create an instance of CourseEvalForm, set its courseNumber to the value of the argument, and open the interface. The definition is as follows:

### openOnCourse: aString

“Assign aString as course name and open Course Evaluation form.”

| form |

form := self new.

“Create an instance of CourseEvalForm.”

form courseNumber: aString.

“Assign its course number.”

self openOn: form

“Open, using an instance opening message.”

The accessing method *courseNumber*: assigns new value to instance variable *courseNumber*, and the last line introduces a new built-in opening message called *openOn*. The receiver of this method is an *instance of the application model* (*openOn*: is thus an *instance method*), and the method assumes that the specification of the window is stored in the default class method *windowSpec*. There are several other opening messages and we urge you to explore them. The *new* method is inherited from *ApplicationModel* and it sends the hook message *initialize* and all the rest as usual. We will use *initialize* to define the initial setting of the radio buttons to ‘n/a’ in the way explained earlier:

### initialize

“Initialize aspect value holders of all rows to n/a for initial display”

| symbols |

symbols := #(#answer1 #answer2 #answer3 #answer4 #answer5 #answer6 #answer7 answer8 #answer9 #answer10 #answer11 #answer12 #answer13).

symbols do: [:answer| (self perform: answer) value: 'n/a' asValue]

Some might consider this solution somewhat unsatisfactory because all elements of array symbols are essentially the same and we should not have to type them one after another. As an alternative, we can construct the symbols from strings, using the shared part *answer* and appending the index as follows:

### initialize

“Initialize aspect value holders of all rows to n/a for initial display”

1 to: 13 do:

[:index| (self perform: ('answer', index printString) asSymbol) value: 'n/a' asValue]

The only other method that we must write is for handling the *Print and close* button. Its principle is as follows:
### printAndClose

"Gather answers, close window, and print results in Transcript."
"Collect all answers, the comment, and the course number."
"Close the window."
"Print the result in Transcript."

Collecting the answers will probably require many messages and we will thus define a separate message gatherAnswers to do this. The definition is now as follows:

### printAndClose

"Gather answers, close window, and print results in Transcript."
self gatherAnswers.
"Close the window."
self closeRequest.
"Print results in the Transcript"
Transcript clear; show: 'Evaluation of course ', courseNumber value; cr; cr.
1 to: answers size do: [:index | Transcript show: 'question ', index printString, ':'; tab; show: (answers at: index); cr].
Transcript show: comment value

To finish the program, we need the definition of gatherAnswers which produces the array of answers. The solution can be described as follows:

* For Question 1, find the value of instance variable answer1 and insert it into the first element of array answers.

* For Question 2, find the value of instance variable answer2 and insert it into the first element of array answers.

* Similar for questions 3 to 13.

To get the answer for Question 1 and to insert it into the array, we need

answers at: 1 put: answer1 value "Returns, for example 3."

For Question 2, the code is

answers at: 2 put: answer2 value

and so on. Using this style, the definition would become

### gatherAnswers

"Calculates array of answers"
| array |
"Create uninitialized array with 14 elements: 13 for questions, 1 for comment"
array := Array new: 14.
"Calculate values of its elements"
answers at: 1 put: answer1 value.
answers at: 2 put: answer2 value.
answers at: 3 put: answer3 value.
etc.
answers at: 13 put: answer13 value
questions at: 14 put: comment value

Since each question is handled by an almost identical statement, we can again use the perform: message on a dynamically constructed name of the accessing method:

### gatherAnswers

"Calculates array of answers"
answers := Array new: 14.

1 to: 13 do: 
[:row | 
| value | 
value := (self perform: ('answer', row printString) asSymbol) value.
answers at: row put: value asString].
questions at: 14 put: comment value

We leave it to you to fill in the missing pieces and test that the application works.

Main lessons learned:

* In addition to open, ApplicationModel provides several other application opening methods such as openOn: Some of them are class methods, others are instance methods, but all send hook methods.

Exercises

1. Implement the example from this section.

2. Check how the openOn: method in ApplicationModel works.

3. Study and describe the interface opening protocols on the class and the instance sides of ApplicationModel.

A.1.9 A (very) simple computerized Tax Form – controlling window closure

In this section, we will implement a simple tax form application with the interface in Figure
A.1.19. The input fields at the top are for entering textual information. The fields below are divided into an
income column on the left, a deductions column in the middle, and an information column with short help
text and various action buttons on the right. The *Married Deductions* field is read-only and its contents are
calculated by the program from information about marital status provided by the user. Fields *Taxable Income* and *Total Tax* at the bottom are also read-only and calculated by the program.

The function of the action buttons on the right is obvious but the *Quit* button is a bit more
complex. When the user clicks *Quit*, the program first checks whether at least the first and last names, the
street, the city, and the postal code have been entered. If not, it opens a dialog asking the user whether he or
she really wants to quit. If the user confirms, the program closes the window and quits, otherwise the
request to quit is ignored. The method also checks whether the form has been printed or saved in a file. If
not, it notifies the user and closes only if the user confirms his or her desire to quit. We leave the file saving
operation as an exercise (see Chapter 10 for background material).

Our tax form is a patented improvement on regular government tax forms: Unlike ordinary tax
forms, we allow the user to change the tax rates and the tax brackets (the values of taxable income at which
the tax rate changes) and thus decide how much money the government deserves. Three tax brackets and
corresponding tax rates will be built in as default values.
<figure><img src="image_277.png" /><figcaption>Figure A.1.19. User interface of a simple computerized tax return form.</figcaption></figure>

Design. The problem as stated is again so simple that we don't need a domain model - all data will be kept by the application model which will also do all the processing. If this was a part of a larger application, we would create a domain class to hold the tax information and we leave this extension as an exercise.

As we already know, we will need value holders for *Aspects* of all text fields. We will need some additional variables too: First, variables to hold the limits of tax brackets and the corresponding tax rates. We will call them *limit1*, *limit2*, *limit3*, and *rate1*, *rate2*, and *rate3* respectively. We also need variables to hold information about whether the data has been printed and whether it has been saved, and we will call them *saved* and *printed*. Finally, we will add a variable to keep track of whether the data has changed since the last *save* operation; this variable will be used to ignore *save* requests if there is no new information to be saved. The variable will be called *infoChanged*.

Which behaviors do we need? We must *initialize* value holders so that the window opens with zeros in all numerical fields, and we need *change* methods to change totals and taxes when the user enters new values into numeric fields. We also need change methods to notify *Married Deductions* when the user clicks marital status. Setting these things up will require a *postBuildWith*. Finally, we need *Action* methods for action buttons.
*Implementation.* After painting the user interface and installing it, we specify the properties of all widgets and *Define* the necessary instance variables and stubs of *Aspect* and instance methods. We chose the following properties:

* For input fields intended for monetary values, we choose *Type FixedPoint(2)*.

* For input fields used for input of text we choose *Type String*.

* We chose names of *Actions*, *Aspects*, and *Select* parameters to match the function of the corresponding widgets (for example, `#business`, `#city`, `#single`) to minimize confusion.

* We chose background colors to indicate which fields are to be filled by the user (white) and which fields are calculated by the program (pink).

The requirements on initialization are similar to those in the Restaurant Menu because most value holders must send a message when their value changes. Note that all input fields send the same message to recalculate the totals and make sure that they are properly displayed. Finally, some variables, such as tax bracket limits, must be initialized to default values:

**postBuildWith: aBuilder**

**| symbols |**

"Define change messages by taking advantage of accessing methods."
symbols := #(#business #city #disability etc.).

symbols do:

[:aspectSymbol | (self perform: aspectSymbol)
      ChangeSend: #newTotals to: self)].

"Initialize Aspect value holder for marital status radio buttons."
maritalStatus value: #single.

"Initialize tax bracket limits and rates."

"Change of values must cause recalculation and redisplay of totals - use value."
(limit1 := 5000 asValue) onChangeSend: #newTotals to: self.

(limit2 := 20000 asValue) onChangeSend: #newTotals to: self.

(limit3 := 40000 asValue) onChangeSend: #newTotals to: self.

(rate1 := 0.1 asValue) onChangeSend: #newTotals to: self.

(rate2 := 0.2 asValue) onChangeSend: #newTotals to: self.

(rate3 := 0.3 asValue) onChangeSend: #newTotals to: self.

"We have not changed, saved or printed the information yet."

infoChanged := false.

printed := false.

saved := false.

Note that we stored tax bracket limits and rate values in value holders even though they are not attached to any widgets. This means that we can send them `onChangeSend:` messages and that change of their values will automatically cause recalculation of totals and redisplay. This is a common and very useful application of value holders.

Our next task is to write the definition of `newTotals`. The underlying algorithm is a simple implementation of tax rules:

1. Calculate total income.

2. Calculate deductions, taking into account marital status.

3. Calculate taxable income as difference between income and deductions.

4. Calculate part of taxable income falling into each bracket, and the corresponding tax.

5. Calculate total tax.

6. Assign new values by `value:` to propagate the change to widgets.

The definition based on this algorithm is as follows:
### newTotals

"Something has changed, recalculate and redisplay totals."
| bracket1 bracket2 bracket3 taxable |

"Calculate total income."
totalIncome value: business value + disability value + employment value + farming value +
pension value + rental value.

"Calculate married deduction."
marriedDeduction value: (maritalStatus value == #married
    ifTrue: [500]
    ifFalse: [0]).

"Calculate total deductions."
totalDeductions value: pensionPlan value + unionDues value + businessLoss value +
    childCare value + moving value + marriedDeduction value.

"Calculate taxable income – must not be negative."
taxableIncome value: ((totalIncome value - totalDeductions value) max: 0).
taxable := taxableIncome value.

"Calculate tax for each bracket."
bracket1 := taxable > limit1 value
    ifTrue: [taxable - limit1 value min: limit2 value - limit1 value]
    ifFalse: [0].

bracket2 := taxable > limit2 value
    ifTrue: [taxable - limit2 value min: limit3 value - limit2 value]
    ifFalse: [0].

bracket3 := taxable > limit3 value
    ifTrue: [taxable - limit3 value]
    ifFalse: [0].

"Calculate total tax."
totalTax value: (bracket1 * rate1 value) + (bracket2 * rate2 value) + (bracket3 * rate3 value).

"Reset state variables."
infoChanged := true.
printed := false.
saved := false

We now come to *Action* methods. The *Load* and *Save* buttons are left as an exercise. The *tax brackets* and *tax rates* buttons open a dialog window and offer initial answers, *Help* opens a help window with information about the form, and *Print* constructs a string containing all information entered by the user and sends it to the *Transcript*. We leave these methods as an exercise. Finally, we develop the *quit* method which has the following previously explained tasks:

1. Check whether all required information has been entered.

2. If yes, check whether final information has been printed or saved.

3. If the last condition is satisfied, close the window and terminate the application.

4. In all other cases, a condition has been violated; ask the user to confirm that he or she wants to quit.

The basis of the quit method is the principle that when a window is asked to close, it automatically sends `changeRequest` to its application model. The window then closes if `changeRequest` returns true but the close request is ignored if `changeRequest` returns false. The default definition of `changeRequest` in `ApplicationModel` simply returns true but we can override it with our own `changeRequest` method. By applying these principles, we develop the following definitions:

### quit

"Close the window if everything is OK."
self.closeRequest

and

### changeRequest

"Close the window if everything is OK."
| isIncomplete |
super changeRequest ifFalse: [^false].
"In case a superclass has a handler."
"Is information complete?"
isIncomplete := city value isEmpty or:
    [irstName value isEmpty or:
    [stoffName value isEmpty or:
    [postalCode value isEmpty or: [street value isEmpty]]].
"If incomplete, ask user to confirm and exit if so specified."
isIncomplete
    ifTrue: [^Dialog confirm: 'The form is not complete. Close anyway?'].
    "Has information been printed or saved? Ask for confirmation to close if not."
    (printed or: [saved])
    ifFalse: [^Dialog confirm: 'The form has not been printed or saved. Close anyway?'].
"If we got here, everything is OK or the user confirmed so confirm that window should be closed."
^true

Note that before doing our own processing, we first executed the inherited changeRequest mechanism in case that a superclass provides its own handling of window closure. If this message returns false, the inherited mechanism requires that the window remains open and we thus return false and exit. Otherwise, we continue with our own tests. In our case, we could have skipped this precaution because we know that the only relevant superclass of TaxForm is ApplicationModel and its changeRequest simply returns true. However, executing the behavior defined by superclasses is a good habit and besides, what if somebody later inserted a class between TaxForm and ApplicationModel and this new superclass had its changeRequest?

## Main lessons learned:

* The request to close a window sends `changeRequest` to the application. Its default definition in `ApplicationModel` returns true to close the window. This default behavior can be overridden by redeclaring `changeRequest` in the application model to provide any tests and communication with the user that may be necessary. The method must return true or false.

* At the beginning of a new definition of a method defined in a superclass, always consider whether the superclass behavior should be executed first.

* The use of `ValueHolder` is not restricted to widgets. Value holders are useful whenever we want to broadcast every change of the value of an object to other objects.

## Exercises

1. Implement and test the tax form application.

2. Reimplement the tax form using a domain model and removing all tax processing from the application model.

3. We have not paid much attention to instance variables `saved`, `printed`, and `infoChanged`. Are they all necessary?

4. We used `postBuild:with:` to perform initialization. Could we have done it in the `initialize` method?

5. Modify the tax application to create a `TaxReturn` object and save it in a file. Add `Load` option.

6. Examine and describe the detailed mechanism of window closure, focusing on `changeRequest`.

## Conclusion

In this appendix, we presented radio buttons and check boxes, explained the use of the input field widget, and illustrated these new widgets on several examples. We also explained some of the inner working of the UI builder.

All programmers involved in the design of user interfaces must remember that interface design has two aspects: The technical aspect of declaring the widgets' functionality, and adherence to GUI conventions
and design rules. Ignoring established conventions may make the user interface difficult to use. Conventional uses of buttons and check boxes are as follows: Radio buttons are used to select one of a limited number of known alternatives. When the number of choices is large or when it is not fixed or known beforehand, use single-selection list widgets instead. Check boxes are used individually or in groups of independent boxes to select any number of choices when the number of choices is not large and when the choices are known beforehand. When the number of choices is large or when it is not fixed or known beforehand, use multiple-selection list widgets instead.

The technical aspects of the use of check boxes and radio buttons are as follows: A check box is used for selecting or deselecting a choice. It requires the specification of an *Aspect*, the name of an instance variable holding a Boolean *ValueHolder* representing the state of the box (true for on, false for off). It is also the name of the method accessing this variable. The variable and the method can be automatically defined with *Define* and do not require any further modification if the box is initially off.

Groups of mutually dependent radio buttons achieve their dependence by sharing one *Aspect* - a value holder with the current selection. A radio button has two essential properties: *Selection*, and *Aspect*. The *Selection* is a *Symbol* which is assigned to the shared *Aspect* of the group when the button is clicked on. Each button in a group has its own *Selection* value. Use the *initialize* method to assign a *ValueHolder* with the *Selection* value of the button that should be on when the window first opens to the *Aspect* variable.

An input field is a one-line text editor. Its only essential parameter is *Aspect*, the name of an instance variable holding a *ValueHolder* on the text accepted by the user, and the corresponding accessing method. If the text field is to display text when it opens, a *ValueHolder* with this text must be assigned to the *Aspect* variable in the *initialize* method.

To store the text displayed in an input field in the *Aspect* variable, the user must accept it by pressing <Enter> or by executing *accept* from the field's <operate> menu. Until the user accepts the text, the accepted value may be different from the value displayed and it is thus held in a separate instance variable of the input field.

To force a variable holding a *ValueHolder* to execute a specified message whenever its value changes (via `value:`), send `onChangeSend:` to the variable in the *initialize* method. However, don't forget to assign a *ValueHolder* to the variable first. Alternatively, you can send the `onChangeSend:` message to the value holder directly via the builder or via its accessing method. The message given as the first argument of `onChangeSend:` will be sent whenever the receiver gets a value: message. The second argument is normally self because the change message is usually defined in the application model. The `onChangeSend:` mechanism is the basis for setting up links between widgets.

Each GUI widget may have an ID. IDs of widgets accessed by the same builder must be unique because the builder keeps them in a registry. A widget needs an ID only when we must access it at run time, for example to enable, disable, show, or hide it. Sending `componentAt:` an ID to the builder returns the widget's wrapper. The builder itself can be obtained from the application model.

In addition to the *open* class method for starting an application, *ApplicationModel* contains several other opening methods, both in its instance and in its class protocols. All provide access to the hook methods explained earlier.

In addition to hooks into the window opening process, Smalltalk also provides a hook into the window closing process. To close a window programmatically, send `closeRequest` to the application; this, in turn, sends `changeRequest`. The default definition of `changeRequest` in *ApplicationModel* returns true but this default behavior can be overridden by redefining `changeRequest` in the application model to provide any necessary tests and communication with the user. If the `changeRequest` method returns false, the request to close is ignored. When redefining `closeRequest` and other methods defined in a superclass, consider executing the behavior defined in the superclass first.

Code can sometimes be simplified by constructing messages at run time. The `perform:` message may then be useful.
**Important classes introduced in this chapter**

Classes whose names are **boldfaced** are very important, classes whose names are printed in *italics* are less important, classes whose names are printed in regular font are not of much interest.

DependencyTransformer.

**Widgets introduced in this chapter**

* `checkbox` - used to turn a feature on or off. *Aspect* is a *ValueHolder* on a *Boolean*

* `input field` - one-line text editor. *Aspect* is a *ValueHolder* of accepted text. User must press <Enter> or use
*accept* to store the text in the *Aspect* variable

* `radio button` - used in groups to select one of several mutually exclusive choices. Requires *Aspect* and *Selection* properties. *Aspect* is *ValueHolder* containin *Selection* symbol, shared by all buttons in a group, *Selection* is a symbolic value of *Aspect* for a given button.

**Terms introduced in this chapter**

* *change notification* - specifying that a change in a *ValueHolder* should send a message, usually to the application

* `checkbox` - square button used for turning a selection on or off

* `input field` - one-line text editor

* `radio button` - round button used in groups to select one of several mutually exclusive alternatives

* *registry of named components* - dictionary associating IDs of UI component and their wrappers; held by the application builder

* *Selection property* - Symbol associated with a radio button; assigned to the shared *Aspect* variable when the button is clicked on

* *widget ID* - optional unique ID assigned to a widget so that the application can communicate with it at run time
# Appendix 2 - Dataset, Subcanvas, Notebook, Dialog Window, Menus

## Overview

Dataset widgets look like tables but all their rows have the same structure and display items of the same kind. Individual cells may be check boxes, combo boxes, or input fields.

A subcanvas is a rectangular window area holding another canvas. The contents of a subcanvas area may be changed at run time. One of the main uses of subcanvases is in notebook widgets because each notebook page is a subcanvas.

Notebooks are familiar from the UI Properties Tool. Navigation through notebook pages is via one or two sets of tabs. One set of tags called major tags is required, minor tabs are optional.

A dialog window, also called a modal or pre-emptive window is a window that retains focus (does not let the user activate any other window) until the dialog is closed.

Menus that can be created with the UI Painter include popup menus, menus buttons, and menu bars. Popup menus are the familiar menus that open when the <operate> button is pressed, menu bars are the drop down menus residing on the top of the window, and menu bars are drop down menus that look like input fields.

### A.2.1 Dataset widgets

A dataset looks like a table (Figure A.2.1) but its purpose and behavior are somewhat different. Its main characteristics are as follows:

* Datasets are used to display a list of related multi-component objects, all instances of the same class. (Tables, which are in many ways similar to datasets, can display heterogeneous information.) Two examples of the use of dataset are displaying a list of employees and displaying a list of books in a library catalog.

* All items in the same column of a dataset are accessed by the same method. As an example, items in the *Author* column in Figure A.2.1 might all be accessed by method *author*. Individual cells are accessed by Point coordinates.

* Cells may display text, combo boxes, or check boxes. (Tables display only non-editable text.)

* Dataset cells are directly editable 'in place'.

* The data model of a dataset is a *SelectionInList* object whose *List* components are usually arrays of objects displayed in row cells. As an example, each row in the dataset in Figure A.2.1 is an array whose elements are strings and numbers representing components of *Book* objects including author name, book title, and year of publication. (The model of a table is a *SelectionInTable*.)

* Datasets have simpler decorations.

We will now demonstrate datasets on two examples.

#### Example 1: Dataset as a user interface to a book catalog

*Problem:* Implement the user interface for accessing and editing a catalog of *Book* objects shown in Figure A.2.1. Each *Book* has an *author*, a *title*, and a *year* of publication; *author* and *title* objects are strings, *year* is an integer. All cells in each row must be editable. The interface will be used in conjunction with data stored in a file but for this test, implement it so that it will open with a few *Book* objects already in place; additional books can be entered by the user at run time.
<figure><img src="image_278.png" /><figcaption>Figure A.2.1. Desired library catalog interface.</figcaption></figure>

*Solution:* Two classes are involved in the solution: *Book* (simple subclass of *Object* holding book information - left as an exercise), and an application model (we will call it *LibraryCatalog*). To implement the solution, define *Book*, paint the interface, install it on an application model, define widget properties, and define the necessary methods. The procedure for specifying a dataset is a bit more complicated and must be followed carefully:

1. After painting the dataset widget, specify its *Aspect* property, the name that will return a *SelectionInList* object. We will call it *bookList* (Figure A.2.2).

2. To create the three columns required by the specification, click *New Column* in the *Properties* tool (Figure A.2.2) three times.

3. Specify the properties of each column. To do this, select the column by holding the <Ctrl> key down and clicking the <select> button with the mouse cursor inside the column. The column will be highlighted.

4. Select the *Column* page of the Properties Tool (Figure A.2.3) and fill in the following information<fnref n="1" />:

i. Column label (*String* property) - we chose *Author* for the first column.

ii. *Aspect expression*. This expression will return the data for the cell at the intersection of this column and the row currently selected by the user. Our expression is

### selectedBook author

where *selectedBook* is the name of an instance variable holding a *Book* object (defined in our application model to hold the selected row); *author* is the name of the accessing method that extracts the *author* value from the *Book* object. This method is defined in class *Book*.

iii. Change the width of the column if desired.

iv. Specify the desired *Type* of cell - the available choices are shown in Figure A.2.3 and we selected *Input Field* for each column because we want to be able to edit the cells at run time. Repeat this step for each column (with expression *selectedBook title* and *selectedBook year*). The third column is slightly different because its value *year* is a number and requires *Number* as *Data Type* in the *Column Type* page of Properties. With this type, the widget will automatically convert between the string-based display and the number-based *year* object.

5. Install the canvas and *Define* all properties. Examine the definition of *bookList* in the *aspect* protocol to see its non-trivial character.

<footnote n="1">¹ If the *Column* page is disabled, you have not selected the column in the *Canvas*.</footnote>
<figure><img src="image_279.png" /><figcaption>Figure A.2.2. The essential part of the Basic page of the Properties Tool.</figcaption></figure>

<figure><img src="image_280.png" /><figcaption>Figure A.2.3. The main part of Column Properties.</figcaption></figure>

*Methods:* We will start with the initialize method for LibraryCatalog. It will create the underlying SelectionInList model for the dataset, and initialize its list component. The algorithm is as follows:

1. Create a List whose elements are the rows of the dataset that will be displayed when the window opens. If the window were to open with an empty dataset, we would not put any elements into the List.

2. Create the *SelectionInList* object for the dataset *Aspect* by sending the *Aspect* message *bookList* to the model. Then send the list: message with the list created in Step 1.
The whole definition is as follows:

initialize

"Create and initialize the SelectionInList underlying the dataset widget."

| list authors titles years |

"Create a List object to hold the data."

list := List new.

"Initialize the list - we use three arrays representing columns to do this more compactly."

authors := #('Kerouac' 'Steinbeck' 'Chandler' 'Christie' 'Homer' 'Kundera').

titles := #('On the road' 'The grapes of wrath' 'The sleepy blonde' 'Miss Marple remembers' 'Ilias' 'Farewell party').

years := # (1980 1970 1975 1983 11 1980).

"Create the rows."

1 to: authors size do: [:index | list add: (Book author: (authors at: index)
          title: (titles at: index)
          year: (years at: index))].

"Create the SelectionInList model of the dataset and assign the list to it."

bookList := self bookList list: list "A somewhat malicious use of the identifier list."

We assume that instances of Book are created with the author: title: year: message.

The next task is to create action button methods addBook and removeBook for adding and deleting
rows (Figure A.2.1). The essence of both methods are List messages for adding and removing elements.
Since the dataset widget is the list's dependent, changes to the list automatically redraw the widget.

Adding a row

To add a row, get the SelectionInList model of the dataset using the Aspect message bookList, get
its List via list, and add a new Book object with the add: message. This adds an empty row and the user will
now presumably enter data into it. The definition is

addBook

"Get the List object and add a new item of the appropriate kind."
self bookList list add: Book new

Removing a row

This action assumes that the user has selected a row, and checking that this is indeed so is the first
task of the method. The method asks the SelectionInList object for the index of the selected row. If the index
is 0, no row is selected and no action will be taken. Otherwise, the method sends removeAtIndex: index to
the List. The definition is as follows:

removeBook

| index |
index := bookList selectionIndex.
index = 0 ifTrue: [^self].
bookList list removeAtIndex: index

This completes the solution.
## Example 2: Add sorting buttons to Library Catalog

**Problem:** As an improvement of the library catalog, add three buttons to allow the user to sort book entries by author, by title, or by year. The desired user interface is as in Figure A.2.4.

<figure><img src="image_281.png" /><figcaption>Figure A.2.4. Library catalog for Example 2.</figcaption></figure>

**Solution:** To sort the list by author, we must get the list from the `SelectionInList` object, ask it to sort itself with a sort block based on book authors, and assign the result to `bookList` via the list: message; this takes care of redrawing the dataset via dependency. The definition is as follows:

### byAuthor

"Resort the list by author names and redisplay it."

`bookList list sortWith: [:book1 :book2 | book1 author < book2 author].`

`bookList list: bookList list`

We leave the remaining sorting buttons to you and conclude this section with a comment that may save you some frustration. In our first attempt at `byAuthor`, we wrote the definition as follows:

### byAuthor

`bookList list: (bookList list sortWith: [:book1 :book2 | book1 author < book2 author])`

This did not work because the `sortWith:` message returns a `SequenceableCollectionSorter` rather than the sorted `List`.

### Main lessons learned:

* Dataset widgets look like tables but their behavior and underlying models are different.

* A dataset is essentially a list widget whose individual lines are multi-item objects.

* The underlying dataset objects are `SelectionInList` whose list elements are rows, and a *selected row* object. Cells may be input fields, check boxes, or combo boxes. The nature of each cell in a given column is the same and its contents are obtained via the *Aspect* of the column.

* Row elements are usually consecutive elements of an array.

* The type property of a dataset column ensures automatic conversion between the cell and the internal representation of the displayed object. Built-in types include `String`, `Number`, `Time`, `Boolean`, and others.
* Dataset properties are more complicated than properties of most other widgets and the procedure for creating and using them must be followed carefully.

## Exercises

1. Complete Example 2.

2. Add a *Print* button to the library catalog. In an initial implementation, clicking *Print* will display the catalog in the Transcript in a format similar to the dataset. In a second implementation, *Print* will print the dataset on a printer.

3. One of the data types available for columns is *Text*. Modify the library catalog to display author names in italics. (Hint: Conversion can be performed via the column *Aspect* expression.)

### A.2.2 Subcanvas

Many application windows contain parts that are themselves applications (for example a digital clock). Others contain parts that are swapped with other parts at run time. And many applications contain groups of widgets that are repeated in several windows – the Property Tool is an example. Subcanvases are used in all these situations and they are also the basis of notebook widgets because every notebook page is a subcanvas.

A subcanvas is basically a rectangular window space that displays another canvas. To make it possible to display a canvas in the subcanvas area, the properties of a subcanvas include the name of the class with the specification and support for the inserted canvas, the name of the canvas specification method, and the name of the method returning the application that provides the initial contents of the subcanvas. These properties allow a variety of behaviors but in this section, we will demonstrate only the simplest one - using a subcanvas to swap a part of two alternative versions of a larger canvas back and forth. More complicated uses will be presented later.

#### Example: Using subcanvases to swap a part of a canvas at run time

**Problem:** Create a user interface whose look is controlled by a pair of radio buttons (Figure A.2.5). When the user selects *Interface 1*, the label at the bottom of the window becomes *This is Interface 1*; when the user selects *Interface 2*, the label becomes *This is Interface 2*.

**Solution:** We will implement the two alternative labels as swap-in canvases to illustrate the subcanvas concept. In this case, the same effect could be achieved more easily by changing the label via the builder at run time or by creating the main canvas with both sets of labels, and selectively hiding and showing them as required; but our goal is to introduce the use of a subcanvas in the simplest way possible.

<figure><img src="image_282.png" /><figcaption>Figure A.2.5. The two alternative looks of a user interface.</figcaption></figure>

To solve the problem, we will create three canvases. The first one will be the 'main' window with two radio buttons and a subcanvas widget for the label. The second canvas will provide the first label and the third will contain the second label (Figure A.2.6).
<figure><img src="image_283.png" /><figcaption>Figure A.2.6. The main canvas (left), and the two subcanvases. The subcanvas component of the main canvas is identified only by its handles because we turned its *Ordered* property off.</figcaption></figure>

We start by painting the three canvases with the UI Painter. On the main *Properties* page of the *subcanvas* widget of the main canvas (Figure A.2.7), we must specify the name of the method that returns the application model of the subcanvas specification (*subcanvasAppModel*), and an ID because we will access the subcanvas via the builder to swap a new interface in when necessary.

<figure><img src="image_284.png" /><figcaption>Figure A.2.7. The Basics *Properties* page of the subcanvas widget.</figcaption></figure>

After creating and installing the main canvas (class *SubcanvasTest* and spec method *windowSpec*) we created the two swap-in canvases, exactly as any other canvas, and installed them on the same class with spec methods *interface1* and *interface2* respectively.

The next step is to write an *initialize* method. Its tasks will be to

* initialize the radio buttons so that the window opens with the *Interface 1* button on

* register interest in changes in radio button settings.

The definition is as follows:

**initialize**

“Activate radio button #interface1, register interest in button setting.”

interface := #interface1 asValue.

interface onChangeSend: #newInterface to: self

Next, we must write the change method *newInterface* which is sent when the user clicks a radio button. The method gets the subcanvas, the spec method's symbol (#interface1 or #interface2) from the
aspect variable shared by the radio buttons, and tells the subcanvas to display it. This last step is performed
by the client: spec: message:

newInterface

"Switch to the subcanvas corresponding to the active radio button."

| subcanvas |

"Get subcanvas widget from the builder."

subcanvas := (self builder componentAt: #subcanvas) widget.

"Assign to it the canvas described in the appropriate spec method defined in this class."

subcanvas client: self spec: interface value

Our solution is very simple because we used the same names (#interface1 and #interface2) for both
the *Selection* properties and for the names of the corresponding canvases.

The next task is to write the method that will ensure that the window opens with the correct
subcanvas. The definition simply sends the newInterface message:

postOpenWith: aBuilder

"Display the initial subcanvas."

self newInterface

Note that sending message newInterface at this point is valid because we have already selected a
radio button in initialize. Finally, the method that supplies the application model containing the specification
of the subcanvas returns self because the subapplication is the model itself.

subcanvasAppModel

^self

The builder sends this message when it builds the bindings dictionary associating model names and their values. (Models of widgets such as input fields are their value holders, the model of a subcanvas is the application model that defines it.)

Main lessons learned:

* A subcanvas is a space holder widget that can be used to swap different user interfaces into a predetermined area at run time.

* A subcanvas is specified by a spec method that may be defined in the main application model or in other application models. This makes it possible to swap a whole application into another application.

* If the purpose of a subcanvas is limited to swapping interfaces, the same result can often be achieved by hiding and showing groups of overlaid widgets or by changing the components via the builder at run time.

* The underlying class of the subcanvas widget is SubCanvas. It provides several messages that make it possible to swap in an interface defined in an arbitrary class and window spec method.

* The model of a subcanvas is the application model that defines it.

Exercises

1. Reimplement the example from this section using

i. overlaid widgets and hiding

ii. a single label widget whose value changes at run time.

2. Trace the opening of our example application and write a description of the building process.

A.2.3 Diary - Using a subcanvas to reuse a complete application
In this section, we will build a simple diary with the user interface shown in Figure A.2.8. Clicking a day button in the calendar will display notes stored for this day in the text editor at the bottom of the window. The text can be edited and saved with the *Save notes* button. To switch to another month and year, the user clicks the *New date* button. This opens a dialog requesting the number of the month and the calendar then opens on this new date. When the diary first opens, the calendar displays the date of the day.

<figure><img src="image_285.png" /><figcaption>Figure A.2.8. Diary interface.</figcaption></figure>

When you think about this application, you will realize that the calendar part looks like a useful component that might be reusable in other applications and we will thus create *two* application models - class *Diary* for our problem, and the reusable class *Calendar*. Class *Calendar* will be designed to be used as a new 'widget', somewhat like an extension of the palette, a stand alone application that can be plugged into a subcanvas and provide the necessary communication with its 'master' window and its application model.

## Design and implementation of Calendar

Calendar is a sub-application, the user interface component in the upper half of the Diary window. It displays the currently selected month and year, abbreviated names of the days of the week, and several rows of action buttons with dates. The buttons are arranged to match the days of the week, and the numbers displayed on them correspond to the days in the selected month and year. The layout and contents of the canvas is given by the selected month.

One way to design the day buttons part of the user interface is to use the UI painter to draw enough buttons to satisfy even the most demanding months (Figure A.2.9). To display a calendar for a particular
month, we would then show and enable only the required buttons and display the appropriate number as a label on each of them. We will leave this approach as an exercise and use a different strategy.

<figure><img src="image_286.png" /><figcaption>Figure A.2.9. A month that requires six rows of buttons.</figcaption></figure>

The approach that we will use is to paint all the fixed parts of the calendar (button labels and names of the days of the week) *programmatically*: The builder will add the buttons and change labels to display the correct month and year at building time.

To open the calendar, the builder needs the month and the year to calculate the layout of the day buttons and their number. This information will be stored in two instance variables called month and year, both integers. In principle, the creation message should look like

Calendar month: 3 year: 1996

but since we want to be able to reuse Calendar as a subcanvas, in other words as a part of another application, it must be able to communicate with the application model of the main window. This means that the Calendar must be able to tell the window's model when the user clicks a date button. And to be able to communicate with the master application, the Calendar must have a reference to its application model. We will thus add an additional instance variable called master and the creation message will be as follows:
### newOnMonth: monthInteger year: yearInteger from: appModel

```swc
^(self new) month: monthInteger;
    year: yearInteger;
    master: appModel
```

where month:, year:, and master: are simple accessing messages. The typical use of the method is as in

```swc
Calendar newOnMonth: 3 year: 1996 from: self
```

Our next step is to define the postBuildWith: aBuilder method of Calendar, to add day buttons to the painted background and change the labels. For adding new components programmatically (at run time), UIBuilder provides the add: aComponent method where aComponent is obtained in a way that depends on the component's nature. Examples in class Builder provide templates for several kinds of widgets. In our case, we need an action button and the expression for creating one is

```swc
ActionButtonSpec model: aBlock label: aStringOrText layout: aRectangle
```

where layout: is a Rectangle defining the upper left and lower right corners of the button (in window coordinates), and block: is the action executed when the button is clicked; this is similar to the *Action* property of an action button but arguably more powerful because it is a block rather than a message. The following is an example of a complete button-specifying expression in the context of our creation message:

```swc
aBuilder add: (ActionButtonSpec
    model: [master selection: date] "Evaluated when button is clicked."
    label: date printString
    layout: (x1 @ y1 extent: x2 @ y2))
```

To create a whole array of rows and columns of buttons, we will repeat the button adding statement for every button in the array. Because of the variety of possible month and day layouts, the loop will iterate over six rows and process seven buttons in each. For each button (each row-column cell) it will first calculate the corresponding date. If the date is at least 1 and not greater than the last day of the month, the builder will add the action button with the date displayed. Buttons that don't satisfy the 'within the month' condition are ignored. At the beginning of each new row, the x position (the upper left corner of the button) is reset; at the end of each row, the y position is incremented. The x coordinate is incremented after each column. The complete code to create the buttons is as follows:

```swc
1 to: 6 do: [:row | "Outer loop - one row at a time. Initialize x coordinate of first button."
    x := xStart.
1 to: 7 do: [:column | | date |
    date := boxNumber - startBox. "Convert button position to date."
    (boxNumber >= (startBox + 1) and: [date <= maxDay])
    ifTrue: [ "We have a valid date - add the button."
        aBuilder add: (ActionButtonSpec
            model: [master selection:
                (Date newDay: date
                    monthNumber: month
                    year: year)]
            label: date printString
            layout: (x @ y extent: width @ width))].
            "Calculate position and box number of next button in the current row."
        x := x + width.
        boxNumber := boxNumber + 1].
            "End of row, update the y coordinate for the next row of buttons."
        y := y + width]
```

where boxNumber starts from 1 and startBox is the number of the first day of the month in the week. As a result of the model: argument, clicking a day button sends message selection: with the date corresponding to the clicked button to the master object - the application containing the calendar. Any application using
Calendar will thus have to define method selector: aDate to deal with a new selection in the Calendar sub-application. In the diary application, for example, selection: will check whether a message was recorded for aDate and display it in the text view.

To complete the postBuildWith: method, we must determine how to calculate the date from month and year. To do this, we need to know the first day of the month and the number of days in a month to lay out the buttons and to number them. After examining the protocols of class Date, we find that this information can be obtained as follows:

"Construct the Date object corresponding to the first day of the month."

omatDate := Date newDay: 1

month: (nameOfMonth := Date nameOfMonth: month)

year: year.

"Convertdates to day name and its number within the week."

startBox := Date day攝ofWeek: startDate weekday. "Number of start box in first row."

"Calculate number of days in the current month - needed to recognize last row."

maxDay := Date daysInMonth: nameOfMonth forYear: year.

With this information, we can now write the whole definition:

postBuildWith: aBuilder

"Add day buttons to the fixed part of the interface, change label to show month and year."

| xStart yStart width startBox boxNumber x y nameOfMonth startDate lastDay |

"Change date label to display current month and year."

startDate := Date newDay: 1 month: (nameOfMonth := Date nameOfMonth: month)

year: year.

(aBuilder componentAt: #date)

label: (Label with: (nameOfMonth asString, '', year printString) asText allBold).

"Calculate position of first valid button and the number of days in current month."

startBox := Date day攝ofWeek: startDate weekday. "Number of start box in first row."

lastDay := Date daysInMonth: nameOfMonth forYear: year.

"Initialize upper level corner coordinates of the leftmost button in the first row."

xStart := 10.

yStart := 45.

y := yStart.

width := 32.

boxNumber := 1.

"Execute loop for 6 rows."

1 to: 6 do: [:row | x := xStart. "First button in the row."

1 to: 7 do: [:column | | date | "7 columns."

"Number of date for this position in the button array."

date := boxNumber - startBox.

"Display only buttons corresponding to valid dates in the month."

(boxNumber >= (startBox + 1) and: [date <= lastDay])

ifTrue: [aBuilder add: (ActionButtonSpec

model: [master selection: date]

label: date printString

layout: (x @ y extent: width @ width))].

"Calculate x position for next button in the row."

x := x + width.

"Update button number."

boxNumber := boxNumber + 1].

"Increment y to start of next row."

y := y + width]

This method is too long and we leave it to you to split it into several more elementary methods.
Add accessing methods and test, executing, for example

(Calendar onMonth: 3 year: 1996 master: self) open

<u>A more flexible implementation</u>
One weak point of our new 'widget' is that every application that wants to use it must implement a method called selection: for communication with Calendar. If the master application already has such a method and uses it for another purpose - for example because another sub-application also requires this name - the Calendar class must be redefined. This is, of course, possible, but very undesirable. What if five other sub-applications used the same selector name?

A tempting solution is to rename the method to something that is very unlikely to be used by another sub-application, such as calendarSelection: but this does not guarantee that the name will be unique. As a general principle, 'hardwiring' the name of a communication method of a reusable sub-application is not a good strategy.

If hardwiring is not desirable, we should make the selector 'programmable'. In other words, the master application should tell Calendar what is the name that it want to use for communication as in

Calendar newOnMonth: 3 year: 1996 from: MeetingPlanner message: #calendarSelection:

or

Calendar newOnMonth: 3 year: 1996 from: self message: #selection:

With this approach, any application using Calendar is free to use any 'callback' selector it wants. The implementation of this idea is quite simple. We only need to add a new instance variable to Calendar to hold the name of the callback message, modify the creation message, and change the button handling message which performs the callback (in postBuildWith:).

The new definition of the creation message is

### newOnMonth: monthInteger year: yearInteger from: appModel message: aSymbol

<table><tr><td>^(self new)</td><td>month: monthInteger;</td></tr><tr><td></td><td>year: yearInteger;</td></tr><tr><td></td><td>master: appModel;</td></tr><tr><td></td><td>message: aSymbol</td></tr></table>

where message: is an accessing method for the new instance variable message. The postBuildWith: method which specifies the message sent by clicking the date button must be modified as follows:

### postBuildWith: aBuilder

"Add day buttons to the fixed part of the interface, change label to show month and year."

| xStart yStart startBox boxNumber x y maxDay nameOfMonthdates | etc.

"Calculate position of first valid button and the number of days in current month." boxNumber := 1.

"Execute loop for 6 rows."

1 to: 6 do: [:row | x := xStart. "First button in the row." 1 to: 7 do: [:column | | date | "7 columns."

etc.

(boxNumber >= (startBox + 1) and: [date <= lastDay])

ifTrue: [aBuilder add: (ActionButtonSpec

model: [master perform: message with:

(Date newDay: date month: nameOfMonth year: year)]

label: date printString

layout: (x @ y extent: width @ width))].

etc.

Note an important detail: When the user clicks a day button, its action method evaluates the block
[master perform: message with: (Date newDay: date month: nameOfMonth year: year)]

with arguments date, nameOfMonth, and year. Although the block is not at this point evaluated within postBuild: (this message was already executed), its arguments (temporary variables declared in postBuild:) have the values assigned to them in postBuild:. In other words, the block executes within the context in which it was originally defined, carrying its context with it. This is a very important property of blocks and a reason why blocks should only use their arguments and their own temporary variables if possible.

## An implementation with an adapter

Another way to avoid a hardwired method is to insert a proxy, an adapter, between the two communicating objects (Figure A.2.10). This proxy translates the communication from the 'language' used by the message sender into the language of the receiver, and possibly also in the opposite direction. A class called PluggableAdaptor that performs this tasks for user interface widgets is in the VisualWorks library. This class is designed for a specific purpose in user interfaces and its general use is limited but another pluggable adapter can easily be designed along the same lines. We leave this approach as an exercise.

<figure><img src="image_287.png" /><figcaption>Figure A.2.10. The concept of a proxy/pluggable adapter.</figcaption></figure>

## Design and implementation of Diary

After creating the Calendar sub-application, we are now ready to implement the diary. We will implement it as class Diary, and its task will be to define the user interface, provide communication with Calendar, and hold the diary information (instance variable notes). The window includes the input field (aspect selectedDate), the buttons, the notes Text Editor (aspect note), and a Subcanvas with the Calendar. The Subcanvas properties entered via the Properties Tool will be as follows:

<table><thead><tr><td>Property</td><td>Value</td><td>Purpose</td></tr></thead><tbody><tr><td>Name:</td><td>#newCalendar</td><td>name of Diary method that supplies the new subcanvas</td></tr><tr><td>Class:</td><td>#Calendar</td><td>name of class defining sub-application</td></tr><tr><td>Canvas:</td><td>#windowSpec</td><td>name of Calendar method containing subcanvas specification</td></tr><tr><td>ID:</td><td>#subcanvas</td><td>to provide access the subcanvas</td></tr></tbody></table>

When you define the properties of the date input field, select type *Date* (its value holder will hold a *Date* object) and a suitable display format.

According to the specification, the Diary must open on today's date. If we use the standard open message, we can use the initialization method to assign the proper date to the *Aspect* property of the date text field (we called it *selectedDate*), and initialize the Text Editor:

### initialize

```
selectedDate := Date today asValue.
```

```
notes := Dictionary new
```

For now, we don't assume that the notes are held in a file. We will hold the notes in a Dictionary called *notes* whose keys will be dates and values the corresponding notes, if any.
As the builder builds the canvas, it sends message newCalendar (see table above) to itself to obtain a Calendar and since the Calendar does not yet exist, we must now create it. Using the results of the previous section, the definition of newCalendar is thus as follows:

### newCalendar

"Return and possibly calculate appropriate date by lazy initialization."

```
^newCalendar isNil
```

```
ifTrue: [| date |
        date := Date today.
        ^newCalendar := Calendar
          newOnMonth: date monthIndex
          year: date year
          from: self
          message: #selection:] "Assume callback selector selection:"
        ifFalse: [newCalendar]
```

You can now test that opening a diary with

#### Diary open

gives the desired result.

When the user clicks a date button, class Calendar sends the selection: message (according to the newCalendar method above) which must change the date in the input field (aspect selectedDate) and the displayed note (aspect note). The definition is thus

### selection: aDate

"User clicked a Calendar button. Update displayed date and note accordingly."

```
selectedDate value: aDate.
```

```
note value: (notes at: aDate ifAbsent: ["])
```

As the next step, we will define the *Action* message of the *New date* button. The purpose of this message (we called it `newDate`) is to get a new month and year from the user and display it. To do the display, it will get the subcanvas widget from the builder and send it the client: message with an instance of the calendar constructed for this particular month to open the calendar. The definition is as follows:

### newDate

"Request new date and open calendar on the corresponding month and year with the appropriate note."

| month year sub |

selectedDate value:

```
(Date newDay: 1
    monthNumber:
        (month := (Dialog request: 'Enter number of month' initialAnswer: '') asNumber)
        year: (year := (Dialog request: 'Enter year' initialAnswer: '') asNumber)).
```

"Create new Calendar and assign it to subcanvas."

```
newCalendar := Calendar newOnMonth: month
  year: year
  from: self
  message: #selection:.
sub := (self builder componentAt: #subcanvas) widget.
sub client: newCalendar spec: #windowSpec.
self selection: (Date newDay: 1 month: (Date nameOfMonth: month) year: year)
```

Two functions are still unimplemented: saving of notes in a file (button *Save Notes*) and assignment of a new note to the dictionary when the user clicks *Accept* in the note popup menu. We will leave the popup menu until the end of this chapter when we deal with menus, and saving is left as an exercise.

### Main lessons learned:
* Whenever possible, design classes so that they can be reused in other applications.

* When a part of an application appears to be a candidate for reuse, design it as a stand-alone application and swap it into a new application as a subcanvas.

* If a plug-in sub-application needs to communicate with its master application, create it with a message whose argument provides a link to the master, and equip the master with communication methods so that the sub-application can 'call back' when necessary.

* When a part of the user interface depends on parameters that vary from one execution to another, it may be appropriate to have the builder construct it programmatically.

* To construct a part of the interface programmatically, use `postBuildWith:` and send `add: aComponent` to `UIBuilder` to add components to a previously painted window background.

* To make a reusable component useful, specify its interface messages as symbols and execute them using `perform:`.

* If the message required by another object is not suitable, use an adapter object.

* Blocks carry along the context in which they are defined. To speed up operation and save memory, this context should be minimal and as many arguments as possible should be defined in the block.

## Exercises

1. Modify `newDate` so that the date input field initially displays the date of the first day of the month.

2. Re-implement `Diary` using the other suggested implementation of day buttons and compare the two approaches.

3. Write a code fragment to find all months between 1900 to 1999 that have 31 days and begin on Saturday.

4. None of the `Date` formats available for input fields via the Property Tool looks like the format that we desire. Design a new date format to match our specification. (Hint: See class `InputFieldSpec`.)

5. Write a pluggable adapter with a creation message as in `Translator from: symbol1 to: symbol2 for: anObject` used as in `Translator from: #set to: #setlt for: anObject`. When the translator with these parameters gets message `set`, it sends message `setlt` to `anObject`. Use this principle to re-implement the `Diary`.

### A.2.4 The Notebook widget

In its minimal configuration, the notebook widget is a collection of pages selectable by a tab on the side (Figure A.2.11). Each page is an empty area with a 'book binding' and tabs, and displays a subcanvas determined by the program. Different pages may use different subcanvas definitions or the same canvas definition with different contents. In addition to the required 'major' tabs normally displayed on the side, one can also specify 'minor' tabs along the bottom and change various notebook properties including tab positioning, binding width and location, and colors, either via the Properties Tool or via the builder at run time.
<figure><img src="image_288.png" /><figcaption>Figure A.2.11. The two pages of the notebook in Example 1.</figcaption></figure>

A notebook with tabs is essentially a single-selection list controlled by tabs, and the tab model is thus a `SelectionInList`. If the notebook uses both major and minor tabs, each set of tabs has its own `SelectionInList` model. To define a notebook widget, paint the notebook on the canvas and assign `Aspect` symbols to major tabs and minor tabs (if required). The `Aspect` is a method that accesses the model of the tabs, a `SelectionInList`. Finally, one must define the swap-in subcanvas or subcanvases. The initialization and change response requirements are as follows:

* `initialize`

* assigns a `SelectionInList` with a list of names to the `Aspect` property of the tabs,

* registers interest in the changes of tab selections.

* `postOpenWith:` defines the initial tab selection and the corresponding subcanvas. We will see shortly that specifying the subcanvas is not always necessary.

* The change method registered in `initialize` determines the notebook's response to changed tab selection. If the desired new page uses the same subcanvas as the current page, only the new contents need to be specified. If the new page requires a different subcanvas, the change method must specify it. If the method explicitly assigns the subcanvas, the `postOpenWith:` method does not have to include subcanvas specification because the change message is automatically sent when the notebook opens.

We will now illustrate the basic procedure on a simple example. A more sophisticated use of notebooks is shown in an application developed later in this chapter.

**Example 1: A simple notebook - notebook with major tabs only**

**Problem:** Implement an application consisting of a notebook with the interface shown in Figure A.2.11. The first page contains some rectangles, the second page contains some ellipses, and there are no minor tabs.

**Solution:** Following our outline, paint a canvas with a notebook widget and specify an `ID` (`#notebook`) for accessing the notebook through the builder to display a new subcanvas, and an `Aspect` for major tabs (`#pages`) to access the `SelectionInList` model. This will make it possible to paint new pages (subcanvases) when tab selection changes.

After painting and installing the canvas (class `SimpleNotebook`), create the two canvases representing the two notebook pages making sure that they will fit into the subcanvas of the notebook, and
install them on the same application model as the main window (we called the window spec methods `#page1` and `#page2`). In our example, the geometric shapes are simply *Region* widgets.

The initialization method assigns a `SelectionInList` to the major tab `Aspect` of the notebook and registers interest in changes in tab selections:

**initialize**

"Define tabs and their labels, register interest in tab changes."

pages := SelectionInList with: #('page1' 'page2').

pages selectionIndexHolder ONCHANGE Send: #newPage to: self

Method `postBuildWith:` changes tab selection (see below) and sends message `newPage`. The message is, of course, also sent when the user changes tab selection. The message checks the current tab selection and gets the corresponding subcanvas using the appropriate window spec method:

**newPage**

"Tab selection has changed, display the appropriate page."

| widget |

"Get notebook widget from the builder."

widget := (self builder componentAt: #notebook) widget.

"Display appropriate canvas."

pages selectionIndex = 1

ifTrue: [widget client: self spec: #page1]

ifFalse: [widget client: self spec: #page2]

Method `postOpenWith:` defines the initial tag selection and this change triggers the `newPage` message which selects the subcanvas displayed when the notebook opens. The definition is as follows:

**postOpenWith: aBuilder**

"Specify initial tab selection."

pages selectionIndex: 1

**Example 2: File display - a notebook with major and minor tabs**

*Problem:* Implement an application that allows the user to select a directory, displays the corresponding file names in a notebook, and the contents of the selected file in the adjacent text view (Figure A.2.12).
<figure><img src="image_289.png" /><figcaption>Figure A.2.12. Desired user interface for Example 2 and assignment of widget *Aspect* variables.</figcaption></figure>

**Solution:** This is a simple tool that can be implemented by a single application model class (FileDisplay) with two window specs – one for the main window (windowSpec) and the other for the subcanvas (subCanvas). The required instance variables include *Aspect* variables for major and minor tabs, the list widget, and the text editor. We will call them *alphabet*, * divider*, *files*, and *contents* respectively as indicated in Figure A.2.12. We will also store the string representing the current directory in variable *directoryString*. Figure A.2.14 shows how the *Aspects* of major and minor tabs are specified in the Properties Tool.

<figure><img src="image_290.png" /></figure>
Figure A.2.14. Specifying major and minor tabs for a notebook.

In addition to *Aspect* variables, the program must switch between the two overlapping lists of letters a-to-n and m-to-z corresponding to the two alphabet settings of the major tabs; we will call these lists list1 and list 2. Finally, the file name selected in the list will be used in more than one place and we will assign it another instance variable called filename.

The required methods include initialization, change methods responding to changes in the selection of major and minor tabs and in the filename list, and an *Action* method for the *New directory* button. We must also create the subcanvas containing the list displayed in the notebook. Its specification will be stored in class method subcanvas in the same application model class.

We are now ready for the details and we will start with initialization. Initialization consists of two steps. Method initialize initializes *Aspect* and auxiliary variables, and specifies change messages. Method initialize is as follows:

initialize

| offset |

"Calculate tab labels. They are one-letter strings containing consecutive letters of the alphabet."

list1 := Array new: 14.

list2 := Array new: 14.

offset := $a asInteger - 1.

1 to: list1 size do: [:index | list1 at: index put: (String with: (index + offset) asCharacter)].

1 to: list2 size do: [:index | list2 at: index put: (String with: (index + offset + 12) asCharacter)].

"Define major and minor tabs. Minor tabs are fixed, major tabs depend on the selected minor tab."

alphabet := SelectionInList with: list1.

divider := SelectionInList with: #('a-n' 'm-z').

"Define change messages for notebook tabs."

alphabet selectionIndexHolder ONChangeSend: #changedLetter to: self.

divider selectionIndexHolder ONChangeSend: #changedHalf to: self.

"The contents of the file list will initially be files in C:\ starting with letter a."

files := SelectionInList with: ((filename := Filename named: 'C:\') directoryContents
select: [:fName | (fName at: 1) asUppercase = $A]).

files selectionIndex: 0. "No file is initially selected."

"Change of filename list selection triggers a change message."

files selectionIndexHolder ONChangeSend: #newFileSelection to: self.

"Select the 'a' major tab initially."

alphabet selectionIndex: 1

Note that there is no difference between the principles of treatment of major and minor keys.
Assignment of label to the window and assignment of the subcanvas to the notebook page happens in
postOpenWith: because it depends on the bindings dictionary:

postOpenWith: aBuilder

postOpenWith: aBuilder

"Assign window label."

self builder window label: 'Files in directory: c:\.'

"Assign the file list subcanvas to the notebook page."

(aBuilder componentAt: #pageHolder) widget client: self spec: #subCanvas

Our next definition is the *Action* method of the *New directory* button. It gets the name of a new directory from the user, and checks that it corresponds to an existing directory name. If it does, it first changes the label of the window to show the filename. It then resets major and minor buttons to show letter a, and assigns a new value to the filename list value holder, triggering its redisplay with new file names, all starting with $A. Via the implicitly invoked change message, this also blanks the text editor view.

newDirectory

"Get directory name and switch to it if it is valid."

| dirString dirName |

dirString := Dialog request: 'Enter complete filename path as in C: or C:\visual' initialAnswer: 'C:'.
```
dirString empty? | (dirName := dirString asFilename) isDirectory not
    ifTrue: [^Dialog warn: dirName asString, ' is not a valid directory.']
    ifFalse: [directoryString := dirString].
    self builder window label:
        ('Files in directory: ', directoryString copyWith: Filename separator).
divider selectionIndex: 1.
alphabet selectionIndex: 1
```

Finally the change messages. When the user makes a new selection in the filename list, we must check whether a file is now selected or not and if it is, display it by changing the value of the value holder of the text editor. The display will, of course, work only for ASCII files.

### newFileSelection

```
"A new file has been selected. Display its contents or blank Text Editor for no selection."
| text |
files selectionIndex = 0
    ifTrue: [text := "']
    ifFalse: [text := ((directoryString copyWith: Filename separator), files selection)
        asFilename contentsOfEntireFile].
self contents value: text
```

The change message for major tabs checks whether a tab is selected. If there is no selection, we select tab a because the initial display of the notebook would otherwise cause problems via change messages that depend on tab selection. We then use the value of the major tab to find all files in the current directory starting with the selected letter and assign them to the filename list. This redraws the list and sends a change message (see initialization) that blanks the text editor view.

### changedLetter

```
"User selected new major tab, display new list of files."
| path |
alphabet selectionIndex = 0 ifTrue: [alphabet selectionIndex: 1].
path := directoryString copyWith: Filename separator.
files list: (path asFilename directoryContents
    select: [:string | (path, string) asFilename isDirectory not & (
        (string at: 1) asUppercase = (alphabet selection at: 1) asUppercase))
```

Note the use of Filename separator which makes the path platform independent – different platforms select appropriate separators. Finally the change message for minor keys. When minor key selection changes, major keys must display the appropriate part of the alphabet. The message also selects the first letter of the list as the major tab selection, calculates the corresponding filename list, and assigns it to the list value holder. Through change messages, this modifies the contents of the text editor as well.

### changedHalf

```
"Minor tab selection has changed. Display the alternative list of minor tabs and propagate changes."
| letter |
divider selection = 'm-z'
    ifTrue: [alphabet list: list2.
        letter := $m]
    ifFalse: [alphabet list: list1.
        letter := $a].
files list: (filename directoryContents select: [:˝name| (˝name at: 1) asUppercase = letter])
```
## Main lessons learned:

* A notebook is a list of pages accessed by tags.

* Up to two sets of tabs can be defined - major and minor. Major tabs are required, minor tabs are optional.

* Each set of tabs uses its own `SelectionInList` as its model.

* Each notebook page is a subcanvas holder.

* All pages in a notebook may use the same canvas and differ only in the displayed information. Alternatively, different pages may insert different canvases into their subcanvas.

* Flipping pages is achieved by change messages triggered by tag selections.

* Major and minor tabs are handled identically.

## Exercises

1. Why didn't we use `postBildWith:` instead of `postOpenWith?:` Try it.

2. Modify the Diary to use a notebook instead of a text editor for notes.

3. Implement Example 2.

4. Trace change in tab selection.

## A.2.5 Dialog windows

A dialog window is the window used by `Dialog` class messages such as `confirm:` and `warn:`. Its distinguishing feature is that it is *modal* or *pre-emptive*, which means that it does not give up control until it is closed. In other words, you must finish all interaction and close the window before you can interact with another window. This behavior is implemented in class `SimpleDialog`, a subclass of `ApplicationModel`. In this section, we will explain how to create your own dialog window. Although modal windows provide an interesting and sometimes necessary behavior, user interface experts discourage their indiscriminate use because they restrict user's freedom.

There are several ways to make a window pre-emptive. One way is to *install* a canvas as a *Dialog* instead of an *Application*, making its model a subclass of `SimpleDialog` instead of `ApplicationModel`. Another possibility is to *install* the canvas as *Application* (its model is thus a subclass of `ApplicationModel` as usual) but *open* it as a dialog. You can also construct the dialog programmatically from scratch using `SimpleDialog` rather than painting the canvas with the `UI Painter`; this is how dialogs in class `Dialog` are implemented. Finally, you can change the same window from modal to non-modal and vice versa programmatically. Each of these methods has its advantages and disadvantages and we will now give a simple example to illustrate the first two approaches which are most common.

### Example: A password dialog window

**Problem:** A library application requires a password. Create a dialog window that looks like the `request:InitialAnswer:` window but shows asterisks as the user types the text in (Figure A.2.14). The dialog returns the text entered by the user when the user clicks `Accept`, or an empty string when the user clicks `Cancel`.

<figure><img src="image_291.png" /></figure>
Figure A.2.14. Desired look of password dialog window.

Solution 1: Creating a dialog with the UI Painter and installing it as a Dialog

In this implementation, we will create the password dialog as a separate class called PasswordDialog. Creating its user interface is very similar to creating the usual *Application* canvas: Paint the window choosing *password* style and aspect text for the input field, *Install* it on the model class as usual, but specify *Dialog* as the window type (Figure A.2.15). As the figure shows, this makes the application model a subclass of SimpleDialog (which is a subclass of ApplicationModel.)

<figure><img src="image_292.png" /><figcaption>Figure A.2.15. A dialog canvas can be created by defining it as a *Dialog*.</figcaption></figure>

The rest is simple except that we must deal with the fact that when the user closes a modal window, the window can return only true (built-in and unchangeable behavior of method `accept`) or false (built-in and unchangeable behavior of method `cancel`). As a consequence,

`password := PasswordDialog password`

can only return true or false, no matter what the user entered into the dialog window. We thus need a way for the dialog window to communicate its acquired data back to Library. One way to obtain this information is to create a PasswordDialog with a message that tells it who is the sender and what is the message to be used to return the appropriate information. (We used the same approach with subcanvases.) As an example, the opening message could be

`openFrom: anObject onClosing: aMessageSymbol`

and the method in class Library that obtains it will be, for example,

**getPassword**

`PasswordDialog openFrom: self onClosing: #password:`

Assuming this definition, the behavior of the dialog window is as follows: When the user closes the password dialog window, the dialog window closing method will send the `password:` message to the Library
object with the string entered by the user as its argument (Figure A.2.16). Its argument will be the password if the user clicked Accept, and an empty string if the user clicked Cancel.

<figure><img src="image_293.png" /><figcaption>Figure A.2.16. Returning results of a dialog.</figcaption></figure>

The definition of the PasswordDialog opening message is as follows:

**openFrom: anObject onClosing: aSymbol**

"Open password window, get user input, return result to anObject using message aSymbol."

^(self new sender: anObject; callback: aSymbol) open

where sender: and callback: are accessing message accessing instance variables sender and callback:.

To implement this solution, we paint the user interface of our password window, define the *Action* properties of *Accept* (*acceptAndClose*) and *Cancel* (*cancelAndClose*) buttons, and install the canvas on class *PasswordDialog* as a *Dialog*. Note that it is not enough to redefine *accept* and *cancel* because instances of *SimpleDialog* and its subclasses always execute the pre-defined *accept* and *cancel* methods and ignore any other definitions.

Method *acceptAndClose* will send callback to the sender with the string entered by the user as the argument. Method *cancelAndClose* will send callback with an empty string. Both methods conclude by sending *closeRequest* to close the window:

**acceptAndClose**

"Return password to sender and close window."

sender perform: callback with: text value.

self closeRequest

**cancelAndClose**

"Return empty string to sender and close window."

sender perform: callback with: "".

self closeRequest

where sender is an instance variable of class *PasswordDialog* initialized to the argument of *openFrom*: *aSender onClosing: aSymbol* when the window opens. Note that the callback message has an argument.

To test our solution, define *Library* with method *getPassword* as explained above, one instance variable called *password*, and accessing methods *password* and *password:*. To test the dialog window, execute the following expression with *inspect*:

Library new getPassword; password

The password window opens, the inspector opens on *PasswordTest*, and the returned value of *password* is as expected.

*Solution 2: Installing a dialog as an Application and opening it as a dialog*
In this approach, we will install the canvas on Library which is an ApplicationModel. The new interface will be stored in a window spec method called passwordWindow but since the superclass is not SimpleDialog, we will have to open it with openDialogInterface: #passwordWindow rather than open. The new definition ofitat will thus be

getPassword

self openDialogInterface: # passwordWindow

Closing the window will again return true or false and we thus must again define acceptAndClose and cancelAndClose methods for the Accept and Cancel buttons. This time, we will not send closeRequest to close the window because we don't want to close the application but only the password window. To do this, the closing methods will get the current window (the password window), and ask its controller to close the window<fnref n="2" />. In addition, the closing methods will assign an appropriate value to password. The definitions are

acceptAndClose

password := text value.

Window currentWindow controller close

and

cancelAndClose

password := text value.

Window currentWindow controller close

Finally, note that although we implemented the dialog as a part of Library, we could have implemented it as a standalone class just as in Solution 1.

Solution 3: Creating the dialog programmatically via SimpleDialog

Class SimpleDialog contains numerous utility messages for building custom dialog windows programmatically and class Dialog uses these messages to build its utility dialogs. The advantage of this approach is that it provides full control over the behavior of the window, including the returned object. The disadvantage is that it requires more complex programming. We will not demonstrate the procedure but if you wish to see the details, browse request:initialAnswer:onCancel:for: in class SimpleDialog. This method is the basis of the implementation of the familiar request:initialAnswer: method in class Dialog.

Summary of the three approaches

The most common way of creating modal dialogs is to paint the dialog window with the UI painter and install it as a Dialog or as an Application. In both cases, closing the window with accept or cancel returns true or false and if we want to pass another result to the sender of the dialog opening message, we must take extra measures: If the canvas is installed as a Dialog, its class needs to know who is sending the opening message and how to pass the result back. The advantage of this approach is that the dialog is reusable in many situations. If the canvas is installed as an Application, the sender usually is the application model itself and the methods that accept or cancel the result of the dialog can access any of the variables of the application directly. This approach is thus somewhat simpler but the dialog is not reusable because it is a part of the application model.

Main lessons learned:

* A dialog is a modal (pre-emptive) window that does not relinquish control until it is closed.

* The use of modal windows is discouraged because they restrict user's freedom.

<footnote n="2">² For more about controllers, see Chapter 12.</footnote>
* There are three ways to create dialogs in VisualWorks: By painting the canvas and installing it on a subclass of SimpleDialog or a subclass of ApplicationModel, or by constructing the window programmatically as a subclass of SimpleDialog. The first two approaches are easier and more common, the third approach provides more control.

* When installing a dialog as a *Dialog*, define a creation message that identifies the sender and the message to be used to return the result. When the dialog is installed as an *Application* (but opened as a *Dialog*), dialog closing messages can access the application model directly.

* Installing a dialog as a *Dialog* makes the dialog reusable. Installing a dialog as an *Application* and opening it as a *Dialog* is simpler but it ties the dialog interface to the application.

* The nature of a window (application or dialog) can be changed at run time.

## Exercises

1. You may have noticed that if you specify text as the argument for Dialog prompts such as warn:, the emphasis does not have any effect. Find why and modify the code to remove this restriction.

2. One slightly annoying feature of built-in dialogs from class Dialog is that the dialog windows appear at the latest location of the cursor. Define a new class called PositionableDialog with methods replicating the behavior of warn:, confirm:, and request:initialAnswer: but adding position control as in confirmAtPositionFromUser:. (Hint: The opening message openAt: aPoint allows the programmer to specify where the dialog window should open.)

3. Implement similar modifications as in Exercise 2 but open the dialog window in the center of the screen. (Hint: Class Screen provides access to the properties of your computer screen.)

## A.2.6 Menus in general and popup menus in particular

A menu is a collection of labels and clicking a label returns a value, possibly calculated by an expression or a block associated with the label. Functionally, a menu is thus a collection of label-value pairs.

The UI Painter provides three types of menus: popup menus, menu bars, and menu buttons. Popup menus that you can build are the familiar menus invoked by the <operate> button, an example of a menu bar is the list of commands at the top of the Launcher, and a menu button is a drop-down menu that looks like an input field when inactive but drops down a menu when activated (Figure A.2.17). The purpose of menus is similar to the purpose of single-selection lists - selecting one of several items - and their advantage is that they occupy little or no window space. The advantage of selection lists is that they make the choices visible at all times.

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

<figure><img src="image_295.png" /></figure>
Figure A.2.17. Passive (left) and activated (right) menu button. The passive view may display the current choice in the menu. The menu bar at the top of the window has one label.

The distinguishing characteristics of popup menus, menu bars, and menu buttons are summarized in the following table:

<table><thead><tr><td>type of menu</td><td>behavior</td><td>type of GUI component</td><td>placement</td></tr></thead><tbody><tr><td>menu bar</td><td>drop-down</td><td>window property</td><td>top of window, no program control</td></tr><tr><td>menu button</td><td>drop-down</td><td>stand alone widget</td><td>any place in window</td></tr><tr><td>pop up menu</td><td>pop up</td><td>widget property - &lt;operate&gt; menu</td><td>pop ups at cursor location</td></tr></tbody></table>

All types of menus depend on class Menu which holds information about instances of Menultem. The protocol of Menu deals with the menu as a whole and provides methods for adding and removing menu items, hiding them, changing the menu's background color, and accessing individual menu items by their label. Once a menu item is retrieved, the Menultem protocol can be applied to it, for example to define the emphasis of the text of the label. A Menultem may also be a collection of menu items - a submenu - and this recursive structure allows a menu to contain submenus nested to any depth.

## Creating menus

A menu can be created in the following ways:

* Using Menu and Menultem directly. This approach provides most flexibility but it is also most laborious because every detail must be programmed. Use this style only if necessary, for example, if you must use special fonts for labels, change the background color, etc.

* Using an instance of MenuBuilder. This class has a number of convenience methods that are useful to build menus with limited programming. An instance of MenuBuilder is exactly what its name suggests - a tool that builds a Menu object. Once built, this object can be accessed in all ways available through Menu and Menultem protocols.

* Using the Menu Editor. A Menu Editor is a painting tool that eliminates the need to program the contents of the menu explicitly. Its purpose is similar to that of the UI painter - to minimize programming. Being a substitute for programming, it is also less flexible than other methods of menu creation and cannot be used, for example, to create menus that change at run time. Use the Menu Editor when the menu remains unchanged at run time and uses default settings.

The following is a comparison of the three approaches:

<table><thead><tr><td>Name</td><td>Creation method</td><td>Use</td><td>Flexibility</td><td>Accessing</td><td>Programming effort</td></tr></thead><tbody><tr><td>MenuBuilder</td><td>program</td><td>dynamic menus</td><td>medium</td><td>instance method</td><td>medium</td></tr><tr><td>Menu, Menultem</td><td>program</td><td>dynamic menus</td><td>full</td><td>instance method</td><td>large</td></tr><tr><td>Menu Editor</td><td>paint</td><td>static menus</td><td>limited</td><td>class method</td><td>minimal</td></tr></tbody></table>

In this and the following sections, we will now give several examples of creation of simple popup menus and menu bars, leaving menu buttons as exercises.

## Popup menus

Popups are attached to the <operate> button and can be specified for certain widgets including input fields, selection lists, and text editors. They should be used only for commands that are directly related to the widget. Although this sounds natural, many designers don't follow this rule and put, for example, a command to close the window into the popup menu of a list widget contained in the window. This is illogical and confuses the user.
Each widget that allows a popup menu has a default menu. The default popup menu of selection lists is no menu whereas the default popup menu of input fields and text editors is the familiar text editing menu with *copy*, *cut*, *paste*, and other commands. To create a popup menu different from the default, enter the name of the method that returns the menu into the widget's *Menu* property (Figure A.2.18).

<figure><img src="image_296.png" /><figcaption>Figure A.2.18. To create a non-default menu, enter the name of the method that returns the menu in the *Menu* property.</figcaption></figure>

We will now give two examples that show how to create a popup menu using the *Menu Editor* tool and programmatically.

### Example 1: Creating a menu with the Menu Editor tool

The Menu Editor is suitable for creating popup menus that don't change while the application is running. The specification of a menu created with the Menu Editor is stored in a *class* method that describes the menu, somewhat like the window specification method.

**Problem:** Create a popup menu for the selection list in Figure A.2.19. Clicking *add* will open a dialog allowing the user to enter a new string which will then be added to the selection list and displayed. Clicking *delete* will delete the label currently selected in the selection list, if any.

<figure><img src="image_297.png" /><figcaption>Figure A.2.19. Window containing a selection list with a popup menu.</figcaption></figure>

**Solution:** Paint the canvas, install it on an application class (`ListWithPopups1`), and *Define* the properties. (We called the *Aspect* of the list list, and its *Menu* property `listHolderMenu`.) Since the popup menu for the list does not change during execution, we will create it with the Menu Editor tool. Open it from the *Tools* command in the *Canvas tool* or from the `<operate>` menu of the canvas, and enter the label-command pairs (Figure A.2.20). The symbol entered for *Value* is the name of an instance method in the application model that will be executed when the user clicks the label highlighted on the left.
<figure><img src="image_298.png" /><figcaption>Figure A.2.20. Using Menu Editor to create a menu.</figcaption></figure>

After entering the two label-command pairs (*add* – *additem*, *delete* – *deleteitem*), click *Install* under the *Menu* command of the Menu Editor. This will open the dialog in Figure A.2.21. For *class*, enter the name of the menu-accessing *method* previously specified as the *Menu* Property of the selection list, and click *OK*. This creates the resource method describing the menu, and stores it in the *resources* class protocol. By clicking *Test* in the Menu Editor, you can now examine what the menu looks like.
<figure><img src="image_299.png" /><figcaption>Figure A.2.21. Dialog for installing a menu.</figcaption></figure>

In our case, the automatically generated resource definition method is

```
testMenuHolder
"MenuEditor new openOnClass: self andSelector: #testMenuHolder"
<resource: #menu>
^#(#Menu #(
    #(#MenuItem
        #rawLabel: 'add'
        #value: #addItem )
    #(#MenuItem
        #rawLabel: 'delete'
        #value: #deleteItem ) )#(2 ) nil ) decodeAsLiteralArray
```

and executing the comment line opens a Menu Editor on the menu.

You can now open your application and test the popup menu. The *add* and *delete* commands will appear when you press the <operate> mouse button but they will not do anything, of course, because we have not defined the corresponding messages yet. We will define these methods now.

The method implementing the *add* command gets a new label from the user, adds it to the list of labels, and assigns it to the list widget via list:

```
addItem
"Ask user for new label and add it to the list widget."
list list: (list list add: (Dialog request: 'Enter new label' initialAnswer: ""))
```

where the misuse of identifier list is almost not funny any more. To test the method, we opened the dialog window, selected *add*, but when we entered 'label 1', the result was as in Figure A.2.22. This is not what we desired - and a typical problem.
<figure><img src="image_300.png" /><figcaption>Figure A.2.22. Result obtained with the first version of `addItem`.</figcaption></figure>

The error clearly occurs when the method adds the new string to the list. Everything looks OK so we inserted a halt message into `addList` and traced its execution. We found that when we add: the new label, the list part of the selection list ceases to be a List and becomes a `ByteString`. We now realize that the add: message does not return the modified collection (the list) but the argument - in this case the result of the Dialog expression. To correct this, we must send yourself after sending add:.

###，《addItem》

list list: (list list add: (Dialog request: 'Enter new label' initialAnswer: ""); yourself)

This version works correctly.

Finally the definition of the method executing the `delete` command. The method first checks whether the user made a selection. If not, the method does not do anything. If yes, the method gets the current list, removes the current selection from it, and assigns the new list via list:.

###，《deleteItem》

| selection |
selection := list selection.
selection isNil ifTrue: [^self].
list list: ((list list) remove: selection; yourself)

## Example 2: Creating and changing a menu dynamically

**Problem:** The user interface in Example 1 is less than perfect: When no item is selected, the user cannot delete an item and the menu should not offer the `delete` command. For proper operation, we need two different popup menus - one with `delete` and one without it - and display the menu appropriate for the situation. Such a dynamic menu cannot be created with the Menu Editor.

**Solution:** Although the mechanics of the required code is trivial, a minimal understanding of the basics of menu operation is useful and we will thus start with some background information.

As you already know, active widgets consist of the visual part displayed on the screen (the *view*), and the object that tracks user input and responds to it (the *controller*). If a widget has a popup menu, the widget's controller must know what this menu is because the menu pops up in response to mouse button activation and its operation also depends on user input. To be able to do this, the widget's controller is an instance of `ControllerWithMenu` which holds the widget's *Menu* object in an instance variable and if we want to change the menu at run time, we must thus change the contents of this instance variable.

The easiest way to change the *Menu* object is to put it into a value holder and control its contents via `value:`. In our case, the menu changes whenever the user selects or deselects an item in the list, and to implement this behavior, we will register our interest in any change of list selection via `ONCHANGESEND:to:`. When a change of selection occurs, the change message will send `value:` with the appropriate menu to the menu holder. These arrangements will be made in the initialization method which will assign the initial menu to the menu holder and register interest in selection changes:

###，《initialize》
"Assign initial popup menu to the list and register interest in selection changes."
`listHolderMenu := self menuWithoutDelete asValue.`
`list := SelectionInList new.`
`list selectionIndexHolder ONChangeSend: #changedMenu to: self`

The `changedMenu` method will check whether the list has a selection and supply the menu without `delete` if the list has no selection, or the full menu if there is a selection:

### changedMenu

"Context may have changed - assign the appropriate popup menu."
`self listHolderMenu value: (list selection isNil ifTrue: [self menuWithoutDelete] ifFalse: [self menuWithDelete])`

where `listHolderMenu` is the `Menu` method that we specified in the Properties of the list widget:

### listHolderMenu

`^listHolderMenu`

This method is also executed by the builder when it builds the list and its controller. The method that constructs the full menu uses the `MenuBuilder` and its definition is as follows:

### menuWithDelete

"Calculate menu with `add` and `delete` commands."
`| menuBuilder | menuBuilder := MenuBuilder new.`
`menuBuilder add: 'add' -> #addItem; "Label-value pair." add: 'delete' -> #deleteItem.`
`^menuBuilder menu`

This method demonstrates the standard usage of a `MenuBuilder`:

1. Create a new `MenuBuilder` object to build the menu.

2. Provide menu information to the `MenuBuilder` via `add:` and possibly other building messages.

3. Ask the builder to create and return a `Menu` object via `menu`. The `MenuBuilder` uses the information gathered in Step 2 to build a `Menu` object containing `MenuItem` objects and other information. Don't forget to return the menu.

Method `menuWithDelete` is very much the same and we leave it as an exercise. All other methods remain as in Example 1 but the class method `listHolderMenu` should now be deleted because it is not needed any more.

Finally, any menu – whether created programmatically or with `Menu Editor` – is held in a menu holder in the `Aspect` variable specified as the `Menu` property of the list. Consequently, menus created with `Menu Editor` can be also be changed programmatically. The disadvantage is that once the default menu is replaced, it is not accessible as easily and dynamically changing menus are thus normally created as described in this example.

### Overriding the Text Editor and Input Field default menu

The `Text Editor` and the `Input Field` have a pre-assigned popup menu with defined behaviors. As an example, `accept` simply assigns the text to the widget's `Aspect` variable and cannot be easily redefined. Sometimes, we might want to change these behaviors. In our `Diary`, for example, we would like `accept` to add the text in the `Text Editor` to `notes`. To do this, we must modify the `accept` command in the built-in menu and this requires a new menu which can be created as follows:
1. Specify the name of the method that returns the new menu as the *Menu* property of the Text Editor. We will call this menu calculating method *newMenu*.

2. Write the menu creating method (*newMenu* in our case).

3. Write the method executing the menu command (we will call the method that executes *accept saveNote*).

Method *newMenu* builds a new menu as follows:

### newMenu

"Redefine *accept* by building a new menu executing non-default menu methods."

| mb |

mb := MenuBuilder new.

mb "First add predefined command combinations with default behaviors."
    addFindReplaceUndo;
    line;
    addCopyCutPaste;
    line;
    "Now add customized commands."
    add: 'accept' -> #addNote; "This is new."
    add: 'cancel' -> #cancel. "This is standard."

^mb menu

and *mssage addNote* executed by *accept* simply adds a new association consisting of the selected date and the new note to the notes dictionary:

### addNote

"Save new note in notes dictionary."
notes at: selectedDate value put: note value.

### Main lessons learned:

* Menus have the advantage that they don't consume window space.

* UI painter menus include popup menus, menu bars, and menu buttons.

* Popup menus are activated by the `<operate>` button, menu bars are drop-down menus attached to the window, and menu buttons resemble input fields but provide drop-down menus.

* The basis of all menus is *Menu* containing *Menultem* objects and other information.

* Menus are usually created with the Menu Editor tool or programmatically via a *MenuBuilder*.

* The *Menu* Editor creates a menu stored as a resource specification and limits programming to writing methods implementing menu commands. Such a menu is not intended to be changed at run time.

* Dynamically changing menus can be programmed using *MenuBuilder*.

* *MenuBuilder* constructs a *Menu* object via convenience messages.

* Controllers of widgets with a popup menu have an instance variable containing a value holder with the menu. This variable is specified as the *Menu* property of the widget.

* When adding a new command to a menu, a common mistake is to forget that *add*: returns its argument.

* Text Editor and Input Field have popup menus with default behaviors. To change the behavior, build a new menu using *MenuBuilder*.

### Exercises

1. Class *Menu* has a rich set of controls over the form of the label and the way in which menus are constructed. Write a description of *Menu* and *Menultem* with detailed information about three selected protocols and five selected methods.

2. The *Menu* Editor provides a number of interesting options such as adding an image to a menu item, indenting, allowing ID access to a menu item, and so on. Write a summary of its functions. (Hint: See on-line help.)
3. Use the Menu Editor to color the background of the *delete* command in our example red and the *add* command green.

4. Add command *edit* to the popup menu in Example 2. The menu should show it only when a label is selected and it should allow the user to change the selected list item via a dialog.

5. Instead of removing the *delete* command when there is no selection, disable it. (Hint: See the example class protocol in class *Menu*.)

6. Modify the Text Editor menu in Diary to display *accept* in boldface, and *cancel* in red.

7. Track how a menu holder is accessed during the opening and operation of an application.

8. Find how the builder determines whether to use a class method or an instance method to construct a menu.

9. Track and describe the complete sequence of events that occur when a popup menu is activated by pressing the <operate> mouse button.

10. Find where the `<window>` popup menu is defined and modify it to display the *close* command in red.

### A.2.7 Menu Bars

A menu bar is a set of labels at the top of a window and their associated drop-down menus (Figure A.2.23) called submenus. To assign a menu bar to a window, enter the name of the method returning the menu as the *window's Menu* property. In other respects, menu bars are just like popup menus.

**Example: Window with a menu bar**

**Problem:** Implement a window with a text editor and a menu bar as in Figure A.2.23. The *File* command's submenu will contain two commands called *Print* and *Exit*. The *Print* command will print the contents of the text view in the Transcript, and the *Exit* command will close the window. The *Configure* command's submenu will also contain two commands - *Hide Text* and *Show Text*. When the window opens, the text view will be visible, *Hide Text* enabled, and *Show Text* disabled. Clicking *Hide Text* will make the text view invisible, enable *Show Text*, and disable *Hide Text*. Clicking *Show Text* will have the opposite effect.

<figure><img src="image_301.png" /><figcaption>Figure A.2.23. Window with menu bar and text subview.</figcaption></figure>

**Solution:** Paint the window, enable its *Menu* property, and provide the name of the menu-returning message (*menuBar*) as its *Aspect*. Paint the text view and define its properties (*Aspect text*) including an ID (#text) so that we can control its state.

The next step is to define the methods. We will start with the window's *Menu* method *menuBar* which creates the menu bar with its submenus. A static menu can be built the Menu Editor, remembering that the menus are submenus and using the left- and right-pointing arrows in the Menu Editor to achieve the layering. In this example, however, we will create the menu using the *MenuBuilder* to illustrate how to create submenus programmatically.
### menuBar

"Create instance of Menu for the menu bar."
| menuBuilder |
"Create instance of Menu for the menu bar."
| menuBuilder |
"Create a MenuBuilder."
menuBuilder := MenuBuilder new.
"Use it to construct submenus."
menuBuilder beginSubMenuLabeled: 'File'; "This label appears in the menu bar."
    add: 'Print' -> #print; "Drop-down menu starts here."
    add: 'Close' -> #closeRequest;
    endSubMenu. "Drop-down menu ends here."
menuBuilder beginSubMenuLabeled: 'Configure'; "This label appears in the menu bar."
    add: 'Show text' -> #showText; "Drop-down menu starts here."
    add: 'Hide text' -> #hideText;
    endSubMenu. "Drop-down menu ends here."
"Ask MenuBuilder to construct and return the menu."
^menuBuilder menu

The next step is to write the two methods that enable and disable the *show* and *hide* commands in the drop-down menu. In essence, this consists of extracting the proper components of the menu and changing them. The details are as follows: Ask the builder for the menu bar using the *Menu* property method of the window, extract the submenu *Menultem* of the *Configure* label, and access its menu items. As an example, the *enableHideText* method which enables the *Hide text* command and disables *Show text* is

### enableHideText

"Enable 'Hide text' command and disable 'Show text' command."
| menu submenu |
"Get menu bar menu."
menu := self builder menuAt: #menuBar.
"Get the appropriate submenu."
 submenu := menu valueForMenultem: (menu menultemLabeled: 'Configure').
"Modify the appropriate menu items."
(submenu menultemLabeled: 'Show text') disable.
(submenu menultemLabeled: 'Hide text') enable

The *enableShowText* method which enables the *Show text* command is similar and we leave it as an exercise.

In the process of opening the application, we must enable *Hide* and disable *Show* after the window has been built but before it opens using the *postBuildWith:* method. We do this by sending the *enableHideText* message as follows:

### postBuildWith: aBuilder

self enableHideText

If you now open the window, it will have the correct menu bar and its commands will have the correct submenus. However, the *Configure* commands will not work because we have not defined the methods that *show* and *hide* the text subview widget. These definitions simply get the text editor from the builder, send it *beInvisible* or *beVisible*, and toggle the *Configure* commands. As an example, the *hideText* method is as follows:

### hideText

(self builder componentAt: #text) beInvisible.
self enableShowText

We leave the remaining methods to you as an exercise.

**Main lessons learned:**
* Menu bars are created and used in much the same way as popup menus but a menu bar is a property of the canvas, and the drop down menus are classified as its submenus.

## Exercises

1. Construct the menu bar in our example using the Menu Editor.

2. Draw a diagram showing the structure of the menu bar object being accessed by `enableHideText`. (Hint: Start your search from the builder object.)

3. Modify the *Print* command to open another submenu with two options – *Transcript* (to print to the *Transcript*) and *Printer* (to print to the printer).

## Conclusion

In the first part of this chapter, we introduced datasets. Datasets look like tables but whereas tables can display heterogeneous objects, dataset display rows of objects of the same kind. Unlike tables which are read-only widgets, datasets cells may be editable input fields and other types of widgets.

We then introduced a powerful widget called a subcanvas. A subcanvas is essentially a place holder for a canvas that can be used for swapping of assemblies of UI widgets at run time and for reuse of complete subapplications. Subcanvases are also essential for notebook widgets. While talking about subcanvases, we showed how to use `UIBuilder` to build user interfaces at run time.

Notebooks are widgets that allow access to pages displaying subcanvases. Individual pages may use the same subcanvas and change only its contents, or they may display completely different subcanvases. Access to pages is controlled by major tabs (required) and minor tabs (optional). Tabs are essentially selection lists and both major and minor tabs are handled in the same way.

The next section introduced dialog windows. Dialog windows are modal windows which means that they keep input focus until closed, disabling access to other windows. Because of this imposition on the user, dialog windows are generally discouraged but their use is sometimes necessary. VisualWorks dialog windows are based on class `SimpleDialog` and can be created with the UI Painter. They can be implemented either by specifying their type as *Dialog* instead of *Application* during installation, or by specifying their type as *Application* and opening them with a dialog opening message.

When a VisualWorks dialog window closes, it returns either true or false which is usually unsatisfactory because dialog windows are typically used as forms for entering data. To get around this, the dialog window must either maintain a link to the application class that opens it (if this class is different from the class of the dialog window), or it must be defined in the application class itself and access its instance variables.

In the last part of this chapter, we covered two varieties of menus: popup menus and menu buttons. A third type of menu is a widget called a menu button. The purpose of menus is similar to that of single-selection lists and radio buttons but they occupy less window space. Their disadvantage is that they don't show the choices at all times. All kinds of menus are created in essentially the same way but whereas popup menus and menu bars are associated with windows or widgets, menu buttons are stand alone widgets. When a menu remains the same during the life time of the application, create it with the Menu Editor tool; when it depends on context, construct it at run time.

Text Editor and Input Field are equipped with default popup menus. To change them or to modify their built-in behavior, replace the default menu with one constructed by Menu Editor or `MenuBuilder`.
**Important classes introduced in this chapter**

Classes whose names are **boldfaced** are very important, classes whose names are printed in *italics* are less important, classes whose names are printed in regular font are not of much interest.

**Menu**, **Menuitem**, **SimpleDialog**.

**Widgets introduced in this chapter**

**Dataset** - display resembles tables but internal implementation is based on lists. All rows are instances of the same domain object and all cells in a column thus share the same type which may be selected from input field, read only, combo box or check box.

**Menu Bar** - drop down menu attached to a window. Its components are called submenus and may be nested.

**Menu Button** - drop down menu widget.

**Multiple-Selection List** - list allowing any number of selections at a time.

**Popup Menu** – menu activated by a mouse button. Certain widgets may have associated popup menus which are invoked by sending a menu-constructing method specified as the widget's property.

**Single-Selection List** - list allowing only one selection at a time.

**Subcanvas** – a canvas holder widget. Can be used to include a subapplication as a part of window or switch parts of a window at run time.

**Terms introduced in this chapter**

**adaptor** - object inserted between two communicating objects, typically for the purpose of translating messages from the form used by the sender to the form used by the receiver

**call back** - communication from an object or a program back to the object or program that created it

**controller** - the part of a widget that interact with the user

**view** - the visual part of a widget
# Appendix 3 – Chess board – a custom user interface

## Overview

This appendix shows the details of the design and implementation of an application with a custom UI with its specialized view and controller. It introduces several new techniques for creating and controlling cursors, view updating, and other useful tasks.

### A.3.1 Chess – a specification

In this and the following sections, we will develop a somewhat limited version of a chess front end, as an example of an application using a non-trivial custom widget. The specification of the problem is the subject of this section.

#### Specification

This program will be a pilot version of a program allowing two players to play chess. Eventually, the players may be two humans or one human and one computer program but the pilot version is limited to the design and implementation of the user interface for two human players.

<figure><img src="image_302.png" /><figcaption>Figure A.3.1. Chess board in starting position and cursor indicating white's turn</figcaption></figure>

Each game begins in the standard configuration shown in Figure A.3.1. A player makes a move by clicking the <select> mouse button over the piece to be moved and then over the desired destination square. Before the first click, the cursor has the shape of a letter indicating which player should move - W for White, B for Black. After the first click, the cursor changes to D (for Destination).

If the move specified by the player is legal, the program displays the move on the chessboard. If the first click identifies an empty square or a square occupied by an opponent's piece, the click is ignored.