NSControl
Inherits From: NSView : NSResponder : NSObject
Conforms To: NSCoding (NSResponder) NSObject (NSObject)
Declared In: AppKit/NSControl.h
Class Description
NSControl is an abstract superclass that provides three fundamental features for implementing user interface devices. First, as a subclass of NSView, NSControl allows the on-screen representation of the device to be drawn. Second, it receives and responds to user-generated events within its bounds by overriding NSResponder's mouseDown: method and providing a position in the responder chain. Third, it implements the sendAction:to: method to send an action message to the NSControl's target object. Subclasses of NSControl defined in the Application Kit are NSBrowser, NSButton (and its subclass NSPopUpButton), NSColorWell, NSMatrix (and its subclass NSForm), NSScroller, NSSlider, and NSTextField.
Target and Action
Target objects and action methods provide the mechanism by which NSControls interact with other objects in an application. A target is an object that an NSControl has effect over. The target class defines an action method to enable its instances to respond to user input. An action method takes only one argument: the id of the sender. The sender may be either the NSControl that sends the action message or another object that the target should treat as the sender. When it receives an action message, a target can return messages to the sender requesting additional information about its status. NSControl's sendAction:to: asks the NSApplication object, NSApp, to send an action message to the NSControl's target object. The method used for this is NSApplication's sendAction:to:from:. You can also set the target to nil and allow it to be determined at run time. When the target is nil, the NSApplication object must look for an appropriate receiver. It conducts its search in a prescribed order, by following the responder chain until it finds an object that can respond to the message:
. It begins with the first responder in the key window and follows nextResponder links up the responder chain to the NSWindow object. After the NSWindow object, it tries the NSWindow's delegate.
. If the main window is different from the key window, it then starts over with the first responder in the main window and works its way up the main window's responder chain to the NSWindow object and its delegate.
. Next, it tries to respond itself. If the NSApplication object can't respond, it tries its own delegate. NSApp and its delegate are the receivers of last resort.
NSControl provides methods for setting and using the target object and the action method. However, these methods require that an NSControl have an associated subclass of NSCell that provides a target and an action, such as NSActionCell and its subclasses.
Target objects and action methods demonstrate the close relationship between NSControls and NSCells. In most cases, a user interface device consists of an instance of an NSControl subclass paired with one or more instances of an NSCell subclass. Each implements specific details of the user interface mechanism. For example, NSControl's mouseDown: method sends a trackMouse:inRect:ofView:untilMouseUp: message to an NSCell, which handles subsequent mouse and keyboard events; an NSCell sends an NSControl a sendAction:to: message in response to particular events. NSControl's drawRect: method is implemented by sending a drawWithFrame:inView: message to the NSCell. As another example, NSControl provides methods for setting and formatting its contents; these methods send corresponding messages to NSCell, which actually owns the contents.
See the NSActionCell class specification for more on the implementation of target and action behavior.
Changing the NSCell Class
Since NSControl uses the NSCell class to implement most of its actual functionality, you can usually implement a unique user interface device by creating a subclass of NSCell rather than NSControl. As an example, let's say you want all your application's NSSliders to have a type of cell other than the generic NSSliderCell. First, you create a subclass of NSCell, NSActionCell, or NSSliderCell. (Let's call it MyCellSubclass.) Then, you can simply invoke NSSlider's setCellClass: class method:
[NSSlider setCellClass:[MyCellSubclass class]];
All NSSliders created thereafter will use MyCellSubclass, until you call setCellClass: again.
If you want to create generic NSSliders (ones that use NSSliderCell) in the same application as the customized NSSliders that use MyCellSubclass, there are two possible approaches. One is to invoke setCellClass: as above whenever you're about to create a custom NSSlider, resetting the cell class to NSSliderCell afterwards. The other approach is to create a custom subclass of NSSlider that automatically uses MyCellSubclass, as explained below.
Creating New NSControls
If you create a custom NSControl subclass that uses a custom subclass of NSCell, you should override NSControl's cellClass method:
+ (Class) cellClass
{
return [MyCellSubclass class];
}
NSControl's initWithFrame: method will use the return value of cellClass to allocate and initialize an NSCell of the correct type.
If you want to be able to change the type of cell that your subclass uses (without changing the type that its superclass uses), override setCellClass: to store the NSCell subclass in a global variable, and modify cellClass to return that variable:
static id myStoredCellClass;
+ setCellClass:classId
{
myStoredCellClass = classId;
}
+ (Class) cellClass
{
return (myStoredCellClass ? myStoredCellClass : [MyCellSubclass class]);
}
An NSControl subclass doesn't have to use an NSCell subclass to implement itself; NSScroller and NSColorWell are examples of NSControls that don't. However, such subclasses have to take care of details that NSCell would otherwise handle. Specifically, they have to override methods designed to work with an NSCell. What's more, the lack of an NSCell means you can't make use of NSMatrixa subclass of NSControl designed specifically for managing multi-cell arrays such as radio buttons.
Override the designated initializer (initWithFrame:) if you create a subclass of NSControl that performs its own initialization.
Initializing an NSControl Object
NSControl itself doesn't have a delegate. These delegate methods are declared in NSControl.h but are intended for subclasses, such as NSTextField and NSMatrix, that do have delegates and that allow text editing.
- (BOOL)control:(NSControl *)control Sent directly by control to the delegate; returns YES if the
textShouldBeginEditing:(NSText *)fieldEditor NSControl should be allowed to start editing the text.
- (BOOL)control:(NSControl *)control Sent directly by control to the delegate; returns YES if the
textShouldEndEditing:(NSText *)fieldEditor NSControl should be allowed to end its edit session.
- (void)controlTextDidBeginEditing:(NSNotification *)aNotification
Sent by the default notification center to the delegate; aNotification is always NSControlTextDidBeginEditingNotification. If the delegate implements this method, it's automatically registered to receive this notification.
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
Sent by the default notification center to the delegate; aNotification is always NSControlTextDidEndEditingNotification. If the delegate implements this method, it's automatically registered to receive this notification.
- (void)controlTextDidChange:(NSNotification *)aNotification
Sent by the default notification center to the delegate; aNotification is always NSControlTextDidChangeNotification. If the delegate implements this method, it's automatically registered to receive this notification.