< Previous PageNext Page >

Controls and Menus

Many of the objects you see in an application let you manipulate them to signal intent. These objects include buttons, checkboxes, sliders, table views, file-system browsers, and menus (including the application and pop-up menus). In Cocoa, similar architectures underlie the implementations of the two general kinds of choice-enabling objects: controls and menus. In these architectures, various types of objects, including NSView objects, work together to allow the indication of user choice or intent.

In this section:

Control and Cell Architecture
Menu Characteristics and Architecture
Represented Objects


Control and Cell Architecture

A control is a user-interface object that responds to a user event such as a mouse click by sending a message to another object in an application. Common types of controls are buttons, sliders, and text fields (which typically send a message when users press the Return key). Other, less obvious controls are table views, data browsers, and color wells.

A control is an instance of a subclass of the abstract NSControl. It generally manages one or more cells—instances of a subclass of NSCell, another abstract class. If you look at the Application Kit class hierarchy (Figure 1-9), you notice that NSControl, a subclass of NSView, is the root of a fairly large branch of control classes: NSButton, NSStepper, NSTextField, and so on. At an entirely different location in the hierarchy (under NSObject), NSCell is the start of a branch of cell classes, most of which correspond to a control class: NSButtonCell, NSStepperCell, NSTextFieldCell, and so on.

Note: Two control classes dispense with cells entirely: NSScroller and NSColorWell. Instances of these classes, like any control, enable the user to indicate a choice, but they behave like any non-control view in that they draw themselves and respond to user events without using cells.

Controls That Manage Multiple Cells

Most controls in the Application Kit manage a single cell. In these cases, the control has its cell do almost all of the actual work; it forwards many of the messages sent to it to its cell. But some controls manage multiple cells. The Application Kit takes two general approaches to managing multiple cells within controls:

A single-cell control may seem to be a redundant design, but the value here is with the cell, not the control. See “Rationale for the Control-Cell Architecture” for an explanation.

How Controls Manage Cells

Controls are full-fledged NSView objects. They can be marked as needing display, they are responsible for drawing themselves, they can respond to user events, and they are in the responder chain. At runtime, a control initially behaves like any view. The Application Kit asks it to redraw itself by invoking the control's drawRect: method. If an event message is dispatched to the responder chain and the control implements the appropriate NSResponder method, the control may have an opportunity to handle the event. However, instead of drawing and handling events themselves, controls pass on these responsibilities to their cells. If the control has multiple cells, it also coordinates the behavior of its cells.

As illustrated in Figure 6-21, a control within its drawRect: method typically sends drawWithFrame:inView: to a cell, asking it to draw itself within the passed-in rectangle. Because focus is already locked on the control, the cell can draw itself using the surface of its "host" view. A control in an implementation of a mouseDown: event method sends a trackMouse:inRect:ofView:untilMouseUp: to the cell in which the event occurred. Typically, the cell tracks the mouse events within its border until either the mouse exits or the cell receives a mouseUp: event; then it responds appropriately. (Other event types are handled in a similar manner.)


Figure 6-21  A control coordinating the drawing of a cell

A control coordinating the drawing of a cell

When a cell draws itself, it must represent two aspects. The first is the general appearance of the cell, which is consistent among cells of the same class. These characteristics include cell shape, background color, style, and visual indications of cell state (for example, a checkbox for cell selection or gray text if the cell isn't enabled). The second aspect is the cell's content, which individuates the cell. For content, a cell usually has a title (a string), an image, or in some cases both title and image. The title can be in a specified font. (Some cells, like NSSliderCell, have custom content instead of image or title.)

As content (or part of its content) a cell has an object value and possibly a represented object. The object value must be an object that can be formatted as a string and thus displayed as the cell title—for example, an NSNumber object encapsulating a float value. A represented object, although not displayed, is associated with the cell; for example, a button with a title of "Red" could have an NSColor represented object. For more on object values and represented objects, see “Represented Objects”.

What also individuates most cells is the information they encapsulate for action messages. The target-action mechanism (discussed in “The Target-Action Mechanism” allows a control to send a message to a designated object when the user activates the control (by clicking a button or pressing Return in a text field, for example). The action is a selector that identifies the method to invoke; the target is the designated object. (The target can be nil, which tells the application to search the responder chain for an object that can handle the message; see “Responders and the Responder Chain”.) The abstract NSActionCell class defines the interface for storing and retrieving action selectors and references to target objects. Most NSCell subclasses inherit from NSActionCell.

Rationale for the Control-Cell Architecture

The control-cell architecture in the Application Kit has deep historical roots, going back to the early days of NeXTSTEP. But the necessity for it might seem puzzling at first glance. Why have controls manage cells at all? Why can't controls do the required work themselves?

There's no reason why a control couldn't, and if you are designing a custom control, a cell-less control is certainly a valid approach. But the control-cell architecture brings some advantages with it:

There are also tradeoffs between the use of cells versus subviews for drawing subregions. In the absence of the view invalidation mechanism, the control must take responsibility for figuring out what each cell need to draw on itself. But because views are general purpose objects, a specialized control can often do the required calculations more efficiently.

Note: See Control and Cell Programming Topics for Cocoa for more information about controls, cells, and the architecture enabling them to work together.

Menu Characteristics and Architecture

In addition to controls and cells, users can signal their intentions to an application (as well as to the operating system itself) using menus. A menu is a list of tersely worded choices—or menu items—with potentially nested menus (called submenus). Users typically choose a menu item by clicking it (although other methods are supported); as a result, a command is issued that the active application or operating system acts upon.

Cocoa supports various kinds of menus. Primary among these are the application-specific menus, which in Cocoa are collectively known as the main menu. At runtime, the application-specific menus include theapplication menu (the one bearing the application name) and all the menus to the right of it up through the Help menu. The application-specific menus share the menu bar with the Apple menu and menu extras—the service-specific menus to the right of the application-specific menus. The Application Kit automatically creates and manages certain application-specific menus, such as the Services menu, the Font menu, the Windows menu, and the Help menu. Other types of menus that Cocoa applications can manage include pop-up menus, contextual menus, and dock menus.

Menus and especially menu items have a number of interesting characteristics. Both menus and menu items have a title; the titles of menus are the strings that appear in the menu bar. Menu items can additionally have an image that appears to the left of the title, or they can have an image instead of a title. The title can be an attributed string, allowing different fonts and even text attachments (which permits an image to appear anywhere in the content area of a menu item). Menu items can also have an assigned key called the key equivalent which, when pressed together with modifier keys (except for Shift), causes the same response as a mouse click. Menu items are enabled or disabled, or they can indicate an on or off state; a check-mark appears to the left of the title if the item is in an on state.

Menus and menu items in Cocoa are instances of the classes NSMenu and NSMenuItem, respectively. In a Cocoa application, menus (in a generic sense) are based on a simple design that gives NSMenu and NSMenuItem objects complementary roles. An NSMenu object manages and draws a collection of menu items one below another. It contains an array of NSMenuItem objects representing this collection. An NSMenuItem object encapsulates all the data that characterizes a menu item but does no drawing or event handling itself. An NSMenu object uses the data in each NSMenuItem to draw the menu item within the boundaries of the menu, to track the location of the menu item within the menu, and to send an action message to a target object when users choose the menu item. When drawing, an NSMenu object uses an NSMenuItem object's title and image; for tracking, it uses the item's index; for sending action messages, it uses the action selector and target object stored in an NSMenuItem object.

Pop-up menus make use of this basic menu architecture. However, since they appear within an application's user interface, they have an additional design. Before a user clicks it, a pop-up menu appears as a button-like object. This object is an instance of NSPopUpButton, which manages an NSPopUpButtonCell instance—in other words, the control-cell architecture is used for this initial presentation. The NSPopUpButtonCell object contains an NSMenu object along with its encapsulated NSMenuItem objects. When a user clicks a pop-up button, this embedded menu is asked to display itself.

The menu items in a menu can be validated for the current context and, if an item is not relevant to that context, it can be disabled. NSMenu includes an auto-enabling feature that performs this validation automatically. Before a menu is displayed, it searches the responder chain for an object that can respond to a menu item's action message; if it cannot find any such object, it disables the item. Applications can further refine menu validation by implementing the NSMenuValidation informal protocol.

Contextual menus are implemented in way that's similar to pop-up menus. You can attach an NSMenu object (along with its menu items) to a view using the NSResponder method setMenu:. This menu lists commands specific to the view (which can be validated according to context). When users Control-click or right-click in the view, the menu is displayed.

Further Reading: Application Menu and Pop-up List Programming Topics for Cocoa discusses Cocoa menus and menu items in more detail.

Represented Objects

A cell and menu item can have a represented object, an object that is arbitrarily associated with it. The target of an action message can ask a clicked menu item or cell (sender) for its represented object; the target can then display the represented object, load it, or perform whatever operation is required with the fetched object. A cell or menu item allows clients to access a represented object, and it archives and restores it, but otherwise does not use it.

To understand how you might use represented objects, consider a couple of examples. A matrix contains cells for setting the background color of a text view. These cells have names such as "Light Blue", "Light Gray", "Pink," and so on; the represented object for each menu item is an NSColor object encapsulating the RGB components for that color. Your application might use that represented object as in Listing 6-1.

Listing 6-1  Using a represented object

- (void)changeColor:(id)sender {
    NSColor *repObj = [sender representedObject];
    [textView setBackgroundColor:repObj];  // textView is an outlet
}

Another example would be a pop-up menu in an Info window that allows you to change the displayed pane of settings. Assigned as a represented object to each menu item is an NSView object containing the required set of text fields, controls, and so on.

A represented object is not the same thing as the object value of a control or cell. A represented object is arbitrarily associated while an object value is the value behind what the cell or control displays. For example, an object value for a text field that displays "05/23/2006" would be an NSDate or NSCalendarDate object representing that displayed value. A cell or control's formatter must be able to "understand" an object value. (A formatter is an NSFormatter object).

Represented objects are not strictly limited to cells and menu items. For example, NSRulerMarker objects can have represented objects. And you can design your own custom views to have represented objects.



< Previous PageNext Page >


© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-12-20)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.