There are two components to an application with a GUI in Smalltalk: the application model (the GUI) and the domain model (the underlying implementation that models the problem to be solved). To complete the money calculator application, we 1) implement a domain model for a money calculator, and 2) connect the domain model to the interface model (the GUI/application model).
Open the System Browser . Recall that the four areas across the top of the System Browser are the Category View, the Class View, the Protocol View, and the Method View, and the lower part of the System Browser is the Code View. Scroll down through the categories and select the UIApplications-New category. A template for a class should be displayed in the Code View as depicted in Figure 5.1.
We have defined our class Calculator with instance variables "operand1" and "operand2", whose values represent the values of the two operands used by the calculator. We now complete the implementation of this class in the usual way. To provide the desired functionality, we will implement methods
Replace the entire method template in the Code View with:
operand1 ^operand1
Choose accept from the Code View [Operate] menu. Add the following messages (methods) and choose accept from the Code View [Operate] menu after adding each.
operand2 ^operand2
operand1: aValue operand1 := aValue
operand2: aValue operand2 := aValue
Add the following messages (methods) under the actions protocol in the Code View and choose accept from the Code View [Operate] menu after entering each. This completes the implementation of the Calculator class.
add ^(operand1 + operand2)
sub ^(operand1 - operand2)
Note that we would normally test this class in a workspace before proceeding with the remainder of the implementation. It is left as an exercise for the reader to create an instance of the calculator class and to test the methods that have been defined for the class.
Select CalculatorInterface from the Class View and get the class definition in the Code View. (In order to display the class definition, you will probably have to toggle the category away from, and then back to, UIApplications-New, or alternatively click on the class button and then the instance button, or select definition from the Class View [Operate] menu.) Add an instance variable "calculator" in the class definition as depicted in Figure 5.4, and choose accept from the Code View [Operate] menu.
Make sure that the instance switch is on in the Class View and select add... from the Protocol View [Operate] menu. A dialog box will appear, enter "initialize" and click OK. Modify the method template to match the Code View in Figure 5.5. Choose accept from the Code View [Operate] menu. The System Browser should appear as in Figure 5.5.
To understand what has happened here, recall that the CalculatorInterface class is a subclass of ApplicationModel (see Figure 5.4). The predefined instance creation method (new) for class ApplicationModel creates a new instance of the class and then sends the message "initialize" to the new instance. We have defined the method "initialize" so that it creates an instance of Calculator and assigns it to the instance variable "calculator" of the CalculatorInterface (GUI) instance. Thus when a new instance of our CalculatorInterface is created (e.g., by selecting Start from the Resource Finder) then the "initialize" message will create an instance of Calculator and assign it as the value of the instance variable "calculator" of the interface.
For our money calculator main interface window , recall that we used three data widgets (Operand1, Operand2, and Result) and three action buttons (+, -, and Clear). Thus we must associate instance variables with Operand1, Operand2, and Result, and we must associate methods with +, -, and Clear (and with the menu bar actions as well).
Open the Resource Finder . Select View->User Classes from the Resource Finder Menu. Select the CalculatorInterface class and windowSpec resource on the Resource Finder, as shown in Figure 5.6.
Select Edit from the Resource Finder action buttons. The Canvas, Canvas Tool, and Palette for the windowSpec resource (main money calculator window) should now be displayed.
The effect of specifying an aspect property for an input/output field and using the Define option is to add an instance variable to the interface class for each aspect value. (Thus, the CalculatorInterface class should now have additional instance variables value1, value2, and result. You can check this with a browser.) The value of each instance variable is an instance of class ValueHolder, and this value is displayed in the input/output field whose aspect is the name of the instance variable.
When you specify an action property for an action button and use the Define option, the UIDefiner automatically creates a default method whose name is the value you entered in the Action field using the Properties Tool. When an action button is activated (by selecting it when an application is running), that method is invoked. So you now need to modify the UIDefiner's default methods to provide code that performs add, subtract, and clear actions.
If a System Browser is not open, then open one now. Select the UIApplications-New category, the CalculatorInterface class, and the actions protocol. (If the browser was already open, you may need to deselect the CalculatorInterface class and reselect it to get the actions and aspects protocols.) There should be add, clear, and sub methods in the Method View. Select each of the methods add and sub, and replace its UIDefiner default method with its corresponding code listed below. Remember to choose accept from the Code View [Operate] menu after editing each method.
add calculator operand1: value1 value. calculator operand2: value2 value. result value: calculator add
sub calculator operand1: value1 value. calculator operand2: value2 value. result value: calculator sub
You have now linked the above code to the + and - action buttons on the money calculator main interface window. When + is selected, the message "add" will be sent to the interface window object (CalculatorInterface instance) and when - is selected, the message "sub" will be sent.
The clear method is dependent on the dialog interface. (Recall that we defined a Dialog Window that will pop up when the Clear action button is activated, asking "Do you really want to Clear?".) We first associate the NO and YES action buttons in the dialog window with the predefined methods "cancel" and "accept", respectively.
To access the dialog interface, open the Resource Finder . Select View->User Classes from the menu. Select the CalculatorInterface class in the Class View and then select the dialogSpec from the Resource View. Select Edit from the Resource Finder. The Canvas Tool will appear with the dialog interface on the Canvas. Open the Properties Tool from the Canvas Tool. Select the NO action button, edit the Action field on the Properties Tool, enter "cancel", and click Apply. Select the YES action button, edit the Action field on the Properties Tool, enter "accept", and click Apply.
Install the Canvas for the dialog interface on the CalculatorInterface class and dialogSpec selector as was done at the end of Chapter 4. Close the Properties Tool and the Canvas/Canvas Tool/Palette.
To complete the clear method for the Clear action button, from the System Browser select the CalculatorInterface class, the actions protocol, and the clear method. Replace the UIDefiner default method with the code below. Choose accept from the Code View [Operate] menu.
clear |accepted| accepted := self openDialogInterface: #dialogSpec. accepted ifTrue: [ value1 value: 0. value2 value: 0. result value: 0]
(This method uses the predefined method "openDialogInterface:" to open the dialogSpec dialog window and return its result. The predefined methods "cancel" and "accept", used as actions for NO and YES, return false and true, respectively.)
From a Resource Finder, select the CalculatorInterface class and the menuBar resource. Select Edit, and the Menu Editor will appear. Change the text in the Menu Editor text window as shown in Figure 5.7 to associate the appropriate actions with the menu selections.
(Note: closeRequest is a predefined close action for windows.) Click on Build, then Install to complete the menu bar installation. Close the Menu Editor.
The money calculator is now complete. To save your work, save your image or file out the CalculatorInterface class.
There are many reasons for separating the application and domain models, some of which are obscured by the very simplistic nature of the money calculator example. (This is a common problem when using a simple example to illustrate concepts that are most valuable (or not beneficial except) when applied to complex problems.) These reasons are fairly standard for good object-oriented design and good software engineering practice, and an extensive discussion is beyond the scope of this tutorial. However, some of the reasons are: