In this section we’ll use IB to add more interface
specifications to the Calculator.nib
file,
including customizing buttons further and making several different
types of connections between objects. In order to make connections
which involve an object of the Controller class, we need a
representation of it in IB.
Creating the Controller class isn’t enough: we also need to create an object that is a member of this class, called an instance. Then we have to arrange for the numeric keypad of buttons in the Calculator window to send action messages to the instance whenever these buttons are clicked.
Make sure the Classes tab is displayed in IB’s Nib File window (titled “MainMenu.nib”), then select the Controller class (recall that it’s a subclass of NSObject). If you have trouble finding it, use the Search feature in the window.
Choose IB’s Classes → Instantiate Controller menu command.
This will create an icon called
“Controller” under the Instances
tab in the Calculator’s Nib File window, as shown in
Figure 5-17 (IB automatically displays the Instances
tab view). This icon represents an instance object of the Controller
class — it can be used as the target object of action messages
and also to initialize outlets. You can change the name from
“Controller” to something else if
you like — the name isn’t used for anything
except your convenience in IB. Note the little circles with
exclamation marks in them next to the instances in Figure 5-17. They represent tiny alerts that can be
discovered by mousing over the instances. For example, if you mouse
over the Controller instance, you will discover that its
readout
outlet is unconnected (see Figure 5-17).
Next, we’ll set the buttons on the Calculator’s numeric keypad to the digits 0 through 9 and arrange for each one of them to send a message to the Controller object.
A tag is a reference integer for a Control object that can be set and read in IB’s Info dialog. The purpose of tags is to allow your program to distinguish cells in a user interface from one another, which lets you use the same Objective-C method to handle several different but closely related functions.
To differentiate between the buttons, the Controller object will read the tag of each button.
Double-click the button at the upper-left corner of the matrix in the Calculator window.
The button highlights with a darker version of your current selection color to indicate that it is selected, and the NSButtonCell Info dialog displays information about the button (see Figure 5-18).
If necessary, select Attributes in the pop-up menu in the Info dialog. Note how the window changes to show information about the selected object.
Change the title of the NSButton from “0” to “7” in the Info dialog and hit Return.
Change the tag of the NSButton to “7” at the bottom of the Info dialog and hit Return.
When the Calculator is running and one of the buttons in the matrix of digit buttons is clicked, we’ll arrange for the NSMatrix object to send the enterDigit: message to our Controller object. The Controller object needs to know which button (i.e., which digit) was clicked, so it will send a message back to the sender (the NSMatrix object) to determine which of the button cells in the NSMatrix object was selected. The Controller can then get the tag for that cell and use it in the enterDigit: method as if it were a digit (which is why we set the tags equal to the value of the NSButton).
Change the titles and the tags of the other keypad buttons to reflect the digits that they represent, as shown in Figure 5-19. You can use the Tab key to move between buttons in the NSMatrix, but setting the tags is a bit of a nuisance. (Make sure you set the tags properly — we’ve found that this is an easy place to make a mistake.)
Select the lower-left button in the NSMatrix (it’s invisible in Figure 5-19).
In the NSButtonCell Info dialog, deselect the Enabled switch to make the on-screen button in our running Calculator unclickable.
Now click the Transparent checkbox in the same NSButtonCell Info dialog to make the button disappear, as in Figure 5-19.
Repeat the previous two steps for the lower-right button, so that only 10 of the original 12 buttons in the NSMatrix are used. (See Figure 5-19.)
Click in the Calculator window background (where there are no buttons or text) to select the window, then click the button matrix once to select the NSMatrix as a whole.
Type Command-Ttobring up the Font panel.
As with most Cocoa applications, IB lets you change the font family, typeface, and size of most text it displays. Here we want to change the way our application looks.
Choose the Lucida Grande 14-point font. (You may have noticed that if you make the text inside a standalone button too large for the button to display the information, IB automatically resizes the button. However, IB does not automatically resize the cells inside an NSMatrix if the text is too large to display. This behavior is somewhat inconsistent and may be changed in the future.)
Connect the NSMatrix button object to the Controller instance object by pressing the Control key on the keyboard and dragging the mouse cursor from the middle of the NSMatrix to the Controller instance object icon in the Nib File window, as shown in Figure 5-20.
When you make the connection between the NSMatrix and the Controller instance, it is very important that you press the mouse button when the mouse cursor is over the NSMatrix and release the button when the cursor is over the Controller icon. The order matters, because the NSMatrix will be sending a message to the Controller, not the other way around. (Later in this chapter, we’ll drag the connection in the other direction to accomplish something else.)
Figure 5-20 shows the resulting “connection wire” between the NSMatrix and the Controller instance icon. The small square in the middle of the NSMatrix indicates the source of the connection, while the square around the Controller instance icon indicates the target. Make sure you have connected the whole NSMatrix and not one of the individual buttons in the NSMatrix.
After you release the mouse button, IB will display the NSMatrix Info dialog (see Figure 5-20). You can determine the source object of the connection by the name in the title bar of the Info dialog — in this case, it should be “NSMatrix Info”. The column in the window should include the four action methods we set up earlier in the destination object, namely the Controller instance.
Click the enterDigit: action method and then click the Connect button in the NSMatrix Info dialog. The dimple next to the method indicates that the connection was made. See the NSMatrix Info dialog at the right in Figure 5-20.
When the Calculator program is running, the connection we just made means the following: whenever a user clicks any one of the 10 on-screen digit buttons, the NSMatrix object will send the enterDigit: action message to an instance of our Controller class. The Controller instance is the target and the enterDigit: method is the action.
It’s easy to connect the wrong objects or to disconnect a connection you want, so be extremely careful when making connections and check them in IB if your application isn’t responding properly.
Next, we’ll add clear and clear all buttons in an NSMatrix object, as we did with the digit buttons. This time, however, we’ll connect each button to the Controller object individually — we will not connect the NSMatrix.
Add a matrix of two buttons above the digits matrix in the Calculator window, using the same technique we used earlier (drop a button from the Cocoa-Views palette into the Calculator window and then Option-drag on a selection handle to get two buttons in a matrix).
Rename the two new buttons “C” (for clear) and “CA” (for clear all) and set the font to Lucida Grande 14, the same as for the digit buttons.
Your window should now look similar to the one in Figure 5-21. If you don’t remember how to add a matrix to your window, refer back to Section 5.2.2. If you can’t find the Palettes window, choose IB’s Tools → Palettes → Show Palettes menu command.
Double-click the CA on-screen button to select it. The NSButtonCell Info dialog (not the NSMatrix one) should appear.
Connect the CA button to the Controller instance object icon by Control-dragging from the button to the icon and then double-clicking the clearAll: action in the NSButtonCell Info dialog (double-clicking has the same effect as clicking the action name and then clicking the Connect button). See Figure 5-22.
Similarly, double-click the C on-screen button to select it and then connect it to the Controller instance icon. This time, double-click on the clear: action to complete the connection.
You can make IB show you an existing connection from a source object by first selecting the source object and then clicking either the target or the action method with a dimple in the Connections Info dialog. You might try this by selecting the CA button again and single-clicking the clearAll: action method. Don’t double-click clearAll:, because that will break the connection.
Next, we’ll set attributes of the Calculator’s text (actually numeric) display area:
Select the NSTextField object that is the white display area in the Calculator window.
If necessary, select Attributes in the NSTextField Info dialog (or type Command-1).
Deselect the Editable option in the NSTextField Info dialog (near the bottom) so that the text in the NSTextField object is not editable by the end user of the Calculator.
Be sure that you leave the Selectable option enabled, as this makes it possible for your user to copy the answer into another application. Many programmers inadvertently make their text not selectable or editable, which can produce significant frustration on the part of users!
Set the alignment to be right-justified by clicking the icon that looks like this:
.
If necessary, resize the window. Also, resize the text field so that it goes across the top of the window but stays within the blue guidelines.
The NSTextField Info dialog should now look like the one in Figure 5-23.
The source of all three Calculator connections we’ve
made so far has been a user interface object, while the destination
has always been the Controller
object. In the next connection we make, the direction will be
reversed — the source will be the Controller and the destination
will be an interface object. This second type of connection requires
an outlet, and we will refer to it as an outlet
connection
. Fortunately,
we’ve already declared the outlet that we need
(readout
).
Control-drag from the Controller instance object icon to the NSTextField object. The connection wire (in your current selection color) should look like the one in Figure 5-24.
In the Connections Info dialog, double-click the
readout
outlet to complete the connection, as
shown in Figure 5-24.
Connecting the readout
outlet to the NSTextField
object causes the readout
instance variable in the
Controller object to be initialized to the id of the NSTextField when
the nib section is loaded at runtime. Initializing an outlet in an
instance object is the only way to determine the id of an object
created with IB, so outlets must be used when sending messages to
user interface objects.
Type Command-S in IB to save the MainMenu.nib
file.
3.133.124.21