Copyright ©1995 by NeXT Computer, Inc.  All Rights Reserved.

Control



Inherits From: View : Responder : Object
Declared In: appkit/Control.h



Class Description

Control is an abstract superclass that provides three fundamental features for implementing user interface devices.  First, as a subclass of View, Control 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 Responder'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 Control's target object. Subclasses of Control defined in the Application Kit are Button, Form, Matrix, NXBrowser, NXColorWell, Slider, Scroller, and TextField.



Target and Action

Target objects and action methods provide the mechanism by which Controls interact with other objects in an application.  A target is an object that a Control 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 Control 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.  Control's sendAction:to: asks the Application object, NXApp, to send an action message to the Control's target object.  The method used for this is Application'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 Application 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 Window object.  After the Window object, it tries the Window'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 Window object and its delegate.
Next, it tries to respond itself.  If the Application object can't respond, it tries its own delegate.  NXApp and its delegate are the receivers of last resort.

Control provides methods for setting and using the target object and the action method.  However, these methods require that a Control have an associated subclass of Cell that provides a target and an action, such as ActionCell and its subclasses.

Target objects and action methods demonstrate the close relationship between Controls and Cells.  In most cases, a user interface device consists of an instance of a Control subclass paired with one or more instances of a Cell subclass.  Each implements specific details of the user interface mechanism.  For example, Control's mouseDown: method sends a trackMouse:inRect:ofView: message to a Cell, which handles subsequent mouse and keyboard events; a Cell sends a Control a sendAction:to: message in response to particular events.  Control's drawSelf:: method is implemented by sending a drawSelf:inView: message to the Cell.  As another example, Control provides methods for setting and formatting its contents; these methods send corresponding messages to Cell, which actually owns the contents.

See the ActionCell class specification for more on the implementation of target and action behavior.



Creating New Controls

Since Control uses the Cell class to implement most of its actual functionality, you can usually implement a unique user interface device by creating a subclass of Cell or ActionCell rather than Control.  A Control subclass doesn't have to use a Cell subclass to implement itself; Scroller and NXColorWell don't.  However, such subclasses have to take care of details that Cell would otherwise handle.  Specifically, they have to override methods designed to work with a Cell.  What's more, they cannot be used in a Matrix--a subclass of Control designed specifically for managing multi-cell arrays such as radio buttons.

The initFrame: method is the designated initializer for the Control class.  Override this method if you create a subclass of Control that performs its own initialization.

If your new Control uses a custom subclass of Cell, you'll probably also want to override Control's setCellClass: class method. Since Objective C does not support class variables, if you create a subclass of, for example, Button, and send setCellClass: to your subclass object to use a custom Cell, then all Buttons created after that will also use that Cell class.  There are two ways to circumvent this problem.  One is to reset the Cell class each time you create an instance of your Control subclass.  The other is to override setCellClass: to store its own Cell class in a global variable and to use that in its initFrame: method as follows (note that in the initialize method MyCellSubClass checks itself to prevent its subclasses from inheriting a method that initializes them incorrectly):

static id myStoredCellClass;

+ initialize
{
/* Class initialization code. */
if (self == [MyCellSubclass class]) {
myStoredCellClass = [MyCellSubclass class];  // Default class
}
return self;
}

+ setCellClass:classId
{
myStoredCellClass = classId;
return self;
}

- initFrame:(NXRect *)frameRect
{
id oldCell;

[super initFrame:frameRect];
oldCell = [self setCell:[[myStoredCellClass alloc] init]];
[oldCell free];
/* other initialization code */

return self;
}



Instance Variables

int tag;
id cell;

struct _conFlags {
unsigned int enabled:1;
unsigned int editingValid:1;
unsigned int ignoreMultiClick:1;
unsigned int calcSize:1;
} conFlags;


tag Identifies the Control; used by View's findViewWithTag: method.
cell The Control's Cell (if it has only one).
conFlags.enabled YES if the Control is enabled; relevant for multi-cell controls only.
conFlags.editingValid YES if editing has been validated.
conFlags.ignoreMultiClick YES if the Control ignores double- or triple-clicks.
conFlags.calcSize YES if the cell should recalculate its size and location before drawing.



Method Types

Initializing and freeing a Control
initFrame:
free
Setting the Control's Cell + setCellClass:
setCell:
cell
Enabling and disabling the Control
isEnabled
setEnabled:
Identifying the selected Cell selectedCell
selectedTag
Setting the Control's value setFloatValue:
floatValue
setDoubleValue:
doubleValue
setIntValue:
intValue
setStringValue:
setStringValueNoCopy:
setStringValueNoCopy:shouldFree:
stringValue
Interacting with other Controls takeDoubleValueFrom:
takeFloatValueFrom:
takeIntValueFrom:
takeStringValueFrom:
Formatting text setAlignment:
alignment
setFont:
font
setFloatingPointFormat:left:right:
Managing the field editor abortEditing
currentEditor
validateEditing
Managing the cursor resetCursorRects
Resizing the Control calcSize
sizeTo::
sizeToFit
Displaying the Control and Cell drawCell:
drawCellInside:
drawSelf::
selectCell:
update
updateCell:
updateCellInside:
Target and action setAction:
action
setTarget:
target
setContinuous:
isContinuous
sendAction:to:
sendActionOn:
Assigning a tag setTag:
tag
Tracking the mouse ignoreMultiClick:
mouseDown:
mouseDownFlags
Archiving read:
write:



Class Methods

setCellClass:
+ setCellClass:classId

This abstract method does nothing.  It's implemented by subclasses of Control, which use this method to set the class of their Cells.  Returns self.



Instance Methods

abortEditing
abortEditing

Terminates and discards any editing of text displayed by the receiving Control.  Returns self, or nil if no editing was going on in the receiving Control.  This method doesn't redisplay the old value of the Control.

See also:  endEditingFor: (Window), validateEditing



action
(SEL)action

Returns the action message sent by the Control's Cell, or the default action message for a Control with multiple Cells (such as a Matrix or Form).  To retrieve the action message, this method sends an action message to the Cell.  For Controls with multiple Cells, it's better to get the action message for a particular Cell using:

someAction = [[theControl selectedCell] action];

See also:  setAction:, target, sendAction:to:



alignment
(int)alignment

Returns the alignment mode of the text in the Control's Cell.  The return value can be one of three constants: NX_LEFTALIGNED, NX_CENTERED or NX_RIGHTALIGNED.

See also:  setAlignment:



calcSize
calcSize

Recomputes any internal sizing information for the Control, if necessary, by invoking its Cell's calcDrawInfo: method.  This method doesn't actually draw.  It can be used for more sophisticated sizing operations as well (for example, Form).  calcSize is automatically invoked whenever the Control is displayed and something has changed; you need never invoke it.  Returns self.

See also:  calcSize (Matrix, Form), sizeToFit



cell
cell

Returns the Control's Cell.  You should use selectedCell in the action method of the target of the Control, since a Control may have multiple Cells.

See also:  selectedCell



currentEditor
currentEditor

If the receiving Control is being edited (that is, has a Text object acting as its editor, and is the first responder in its Window), this method returns the Text object being used to perform that editing.  If the Control isn't being edited, this method returns nil.

See also:  abortEditing, validateEditing



doubleValue
(double)doubleValue

Returns the value of the Control's selected Cell as a double-precision floating point number.  If the Control contains many cells (for example, Matrix), then the value of the currently selectedCell is returned.  If the Control is in the process of editing the affected Cell, then validateEditing is invoked before the value is extracted and returned.

See also:  setDoubleValue:, floatValue, intValue, stringValue



drawCell:
drawCell:aCell

If aCell is the cell used to implement this Control, then the Control is displayed.  This method is provided primarily to support a consistent set of methods between Controls with single and multiple Cells, since a Control with multiple Cells needs to be able to draw a single Cell at a time.  Returns self.

See also:  updateCell:, drawCellInside:, updateCellInside:,
drawCell: (Matrix)



drawCellInside:
drawCellInside:aCell

Draws the inside of a Control (the area within a bezel or border). This method invokes Cell's drawInside:inView: method. drawCellInside: is used by setStringValue: and similar content-setting methods to provide a minimal update of the Control when its value is changed.  Returns self.

See also:  drawCell:, drawInside:inView: (Cell), drawCellInside: (Matrix), updateCellInside:



drawSelf::
drawSelf:(const NXRect *)rects :(int)rectCount

Draws the Control.  This method invokes the drawSelf:inView: method of the Control's Cell.  You must override this method if you have a Control with multiple Cells.  Returns self.

See also:  drawSelf:inView: (Cell)



floatValue
(float)floatValue

Returns the value of the Control's selected Cell as a single-precision floating point number.  See doubleValue for more details.

See also:  setFloatValue:, doubleValue, intValue, stringValue



font
font

Returns the Font object used to draw the text (if any) of the Control's Cell.

See also:  setFont:



free
free

Frees the memory used by the Control and its Cells.  Aborts editing if the text of the Control was currently being edited.  Returns nil.

See also:  free (View)



ignoreMultiClick:
ignoreMultiClick:(BOOL)flag

Sets the Control to ignore multiple clicks if flag is YES.  By default, double-clicks (and higher order clicks) are treated the same as single clicks.  You can use this method to "debounce" a Control, so that it won't inadvertently send its action message twice when double-clicked.  Returns self.



initFrame:
initFrame:(const NXRect *)frameRect

Initializes and returns the receiver, a new instance of Control, by setting the value pointed to by frameRect as its frame rectangle.  Makes the new instance an opaque View.  Since Control is an abstract class, messages to perform this method should appear only in subclass methods;  that is, there should always be a more specific designated initializer for the subclass. initFrame: is the designated initializer for the Control class.



intValue
(int)intValue

Returns the value of the Control's selected Cell as an integer (see doubleValue for more details).

See also:  setIntValue:, doubleValue, floatValue, stringValue



isContinuous
(BOOL)isContinuous

Returns YES if the Control's Cell continuously sends its action message to its target during mouse tracking.

See also:  setContinuous:



isEnabled
(BOOL)isEnabled

Returns YES if the Control is enabled, NO otherwise.

See also:  setEnabled:



mouseDown:
mouseDown:(NXEvent *)theEvent

Highlights the Control, and sends trackMouse:inRect:ofView: to the Control's Cell (or whichever Cell the mouse event occured in if the Control has multiple Cells).  This method is invoked when the mouse button goes down while the cursor is within the bounds of the Control.  The Control's Cell tracks the cursor until it goes outside the bounds, at which time the Control is unhighlighted.  If the cursor goes back into the bounds, then the Control highlights again and its Cell starts tracking again. This behavior continues until the mouse button goes up.  If it goes up with the cursor in the Control, the state of the Control is changed, and the action message is sent to the target with sendAction:to:.  If the mouse button goes up with the cursor outside the Control, no action message is sent.  Returns self.

See also:  trackMouse:inRect:ofView: (Cell), sendAction:to:



mouseDownFlags
(int)mouseDownFlags

Returns the event flags (for example, NX_SHIFTMASK) that were in effect at the beginning of mouse tracking.  The flags are valid only in the action method invoked upon the Control's target.

See also:  mouseDownFlags (Cell), sendAction:to:



read:
read:(NXTypedStream *)stream

Reads the Control from the typed stream stream.  Returns self.



resetCursorRects
resetCursorRects

Reestablishes the cursor rectangles for the Control's Cell (or Cells).  If the Cell displays text, and the text in the Cell is selectable, then resetCursorRect:inView: is sent to the Cell. resetCursorRect:inView: in turn, sends addCursorRect:cursor: back to the Control, so that the cursor will change to an I-beam when it enters the Cell's rectangle. Returns self.

See also:  resetCursorRect:inView: (Cell), addCursorRect:cursor: (View)



selectCell:
selectCell:aCell

If aCell is a Cell of the receiving Control and is unselected, this method selects aCell and redraws the Control.  Returns self.



selectedCell
selectedCell

Returns the Control's selected Cell.  The target of the Control should use this method when it wants to get the Cell of the sending Control.  Note that even though the cell method will return the same value for Controls with only a single Cell, it's strongly suggested that this method be used since it will work for Controls with either a single or multiple Cells.

See also:  sendAction:to:, selectedCell (Matrix)



selectedTag
(int)selectedTag

Returns the tag of the Control's selected Cell.  This is equivalent to:

myTag = [[theControl selectedCell] tag];

Returns 1 if there is no selected Cell.  The Cell's tag can be set with ActionCell's setTag: method.  You should only use the setTag: and tag methods in conjunction with findViewWithTag:.  When you set the tag of a Control with a single Cell in Interface Builder, it sets both the tags of both Control and Cell as a convenience.

See also:  sendAction:to:



sendAction:to:
sendAction:(SEL)theAction to:theTarget

Sends a sendAction:to:from: message to NXApp, which in turn sends a message to theTarget to perform theAction. sendAction:to:from: adds the Control as theAction's only argument.  If theAction is NULL, no message is sent. sendAction:to: is invoked primarily by Cell's trackMouse:inRect:ofView:

If theTarget is nil, NXApp looks for an object that can respond to the message by following the responder chain, as detailed in the class description.

Returns nil if no object that responds to theAction could be found; otherwise returns self.

See also:  action, target, trackMouse:inRect:ofView: (Cell),  sendAction:to:from: (Application)



sendActionOn:
(int)sendActionOn:(int)mask

Uses mask to record the events that cause sendAction:to: to be invoked during tracking of the mouse, which is performed in Cell's trackMouse:inRect:ofView:.  Returns the old event mask.

See also:  sendAction:to:, sendActionOn: (Cell), trackMouse:inRect:ofView: (Cell)



setAction:
setAction:(SEL)aSelector

Makes aSelector the Control's action method.  If aSelector is NULL, then no action messages will be sent from the Control. Returns self.

See also:  action, setTarget:, sendAction:to:



setAlignment:
setAlignment:(int)mode

Sets the alignment mode of the text in the Control's Cell, or of all the Control's Cells if it has more than one, and redraws the Control.  mode should be one of:  NX_LEFTALIGNED, NX_CENTERED or NX_RIGHTALIGNED.  Returns self.

See also:  alignment



setCell:
setCell:aCell

Sets the Cell of the Control to be cell.  Use this method with great care as it can irrevocably damage your Control; specifically, you should only use this method in initializers for subclasses of Control.  Returns the old Cell.



setContinuous:
setContinuous:(BOOL)flag

Sets whether the Control will continuously send its action message to its target as the mouse is tracked.  Returns self.

See also:  setContinuous: (ButtonCell, SliderCell), sendActionOn:



setDoubleValue:
setDoubleValue:(double)aDouble

Sets the value of the Control's selected Cell to be aDouble (a double-precision floating point number).  If the affected Cell is being edited, that editing is aborted and the value being typed is discarded in favor of aDouble.  If autodisplay is on, then the Cell's inside (the area within a bezel or border) is redrawn.  Returns self.

See also:  doubleValue, setFloatValue:, setIntValue:, setStringValue:, abortEditing, drawInside:inView: (Cell), isAutodisplay (View), setAutodisplay: (View)



setEnabled:
setEnabled:(BOOL)flag

Sets whether the Control is active or not (that is, whether it tracks the mouse and sends its action to its target).  If flag is NO, any editing is aborted.  Redraws the entire Control if autodisplay is on.  Subclasses may want to override this to redraw only a portion of the Control when the enabled state changes (Button and Slider do this).  Returns self.

See also:  setEnabled: (Cell), isAutodisplay (View), setAutodisplay: (View)



setFloatValue:
setFloatValue:(float)aFloat

Same as setDoubleValue:, but sets the value as a single-precision floating point number.  Returns self.

See also:  floatValue, setDoubleValue:, setIntValue:, setStringValue:



setFloatingPointFormat:left:right:
setFloatingPointFormat:(BOOL)autoRange
left:(unsigned)leftDigits
right:(unsigned)rightDigits

Sets the autoranging and floating point number format of the Control's Cell, so that at most leftDigits are displayed to the left of the decimal point, and rightDigits to the right.  If the Control has more than one Cell, they're all affected.  See the description of this method in the Cell class specification for more detail.  This method doesn't redraw the Control. setFloatingPointFormat:left:right: affects only subsequent invocations of setFloatValue:.  Returns self.

See also:  setFloatingPointFormat:left:right: (Cell)



setFont:
setFont:fontObject

Sets the Font object used to draw the text (if any) in the Control's Cell, or in all the Cells if the Control has more than one.  You only need to use this method if you don't want to use the user's default system font (as set by the user in the Preferences application).  If autodisplay is on, then the inside of the Cell is redrawn.  Returns self.

See also:  font, isAutodisplay (View), setAutodisplay: (View)



setIntValue:
setIntValue:(int)anInt

Same as setDoubleValue:, but sets the value as an integer.  Returns self.

See also:  intValue, setDoubleValue:, setFloatValue:, setStringValue:



setStringValue:
setStringValue:(const char *)aString

Same as setDoubleValue:, but sets the value as a string by copying it from aString.  Returns self.

See also:  stringValue, setStringValueNoCopy:, setStringValueNoCopy:shouldFree:, setDoubleValue:, setFloatValue:, setIntValue:



setStringValueNoCopy:
setStringValueNoCopy:(const char *)aString

Like setStringValue:, but doesn't copy the string.  Returns self.

See also:  stringValue, setStringValue:, setStringValueNoCopy:, setStringValueNoCopy:shouldFree:, setDoubleValue:, setFloatValue:, setIntValue:



setStringValueNoCopy:shouldFree:
setStringValueNoCopy:(char *)aString shouldFree:(BOOL)flag

Like setStringValueNoCopy:, but lets you specify whether the string should be freed when the Control is freed.  Returns self.

See also:  stringValue, setStringValue: setStringValueNoCopy:, setDoubleValue:, setFloatValue:, setIntValue:



setTag:
setTag:(int)anInt

Makes anInt the receiving Control's tag.  Doesn't affect the Control's Cell.  Returns self.

See also:  tag, selectedTag, findViewWithTag: (View), setTag: (Cell)



setTarget:
setTarget:anObject

Sets the target for the action message of the Control's Cell.  Returns self.

If anObject is nil, then when an action message is sent, NXApp looks for an object that can respond to the message by following the responder chain, as detailed in the class description.

See also:  target, setAction:, sendAction:to:



sizeTo::
sizeTo:(NXCoord)width :(NXCoord)height

Changes the width and the height of the Control's frame.  Redisplays the Control if autodisplay is on.  Returns self.

See also:  isAutodisplay (View), setAutodisplay: (View)



sizeToFit
sizeToFit

Changes the width and the height of the Control's frame so that they are the minimum needed to contain the Cell.  If the Control has more than one Cell, then you must override this method.  Returns self.

See also:  sizeToFit (Matrix), sizeToCells (Matrix)



stringValue
(const char *)stringValue

Returns the value of the Control's selected Cell as a string.  If the Control is in the process of editing the affected Cell, then validateEditing is invoked before the value is extracted and returned.

See also:  setStringValue:, doubleValue, floatValue, intValue



tag
(int)tag

Returns the receiving Control's tag (not the tag of the Control's Cell).

See also:  setTag:, selectedTag, tag (Cell)



takeDoubleValueFrom:
takeDoubleValueFrom:sender

Sets the double-precision floating-point value of the receiving Control's selected Cell to the value obtained by sending a doubleValue message to sender.  Returns self.

This method can be used in action messages between Controls.  It permits one Control (the sender) to affect the value of another Control (the receiver) by invoking this method in an action message to the receiver.  For example, a TextField can be made the target of a Slider.  Whenever the Slider is moved, it will send a takeDoubleValueFrom: message to the TextField.  The TextField will then get the Slider's floating-point value, turn it into a text string, and display it, thus tracking the value of the Slider.

See also:  setDoubleValue:, doubleValue



takeFloatValueFrom:
takeFloatValueFrom:sender

Sets the single-precision floating-point value of the receiving Control's selected Cell to the value obtained by sending a floatValue message to sender.  Returns self.

See takeDoubleValueFrom: for an example.

See also:  setFloatValue:, floatValue



takeIntValueFrom:
takeIntValueFrom:sender

Sets the integer value of the receiving Control's selected Cell to the value returned by sending an intValue message to sender. Returns self.

See takeDoubleValueFrom: for an example.

See also:  setIntValue:, intValue



takeStringValueFrom:
takeStringValueFrom:sender

Sets the character string of the receiving Control's selected Cell to a string obtained by sending a stringValue message to sender.  Since this is an action method, there is no alternate like takeStringValueFrom:noCopy:.  Returns self.

See takeDoubleValueFrom: for an example.

See also:  stringValue, setStringValue:



target
target

Returns the target for the action message of the Control's cell, or the Control's target for a Control with multiple Cells.  If nil, then any action messages sent by the Control will be sent up the responder chain, as detailed in the Class Description.

See also:  setTarget:, action, sendAction:to:



update
update

If autodisplay is enabled, sends a display message to itself.  Otherwise it simply sets a flag indicating that the Control needs to be displayed.  This method also makes sure that calcSize is performed.  Returns self.

See also:  updateCell:, updateCellInside:



updateCell:
updateCell:aCell

If aCell is a Cell used to implement this Control, and if autodisplay is on, then draws the Control's Cell; otherwise, sets the needsDisplay and calcSize flags to YES.  Returns self.

See also:  update, updateCellInside:, isAutodisplay (View), setAutodisplay: (View)



updateCellInside:
updateCellInside:aCell

If aCell is a Cell used to implement this Control, and if autodisplay is on, draws the inside portion of the Cell; otherwise sets the needsDisplay flag to YES.  Returns self.

See also:  update, updateCell:, isAutodisplay (View), setAutodisplay: (View)



validateEditing
validateEditing

Causes the value of the Control's selected Cell to be set to the value of the field being edited, if any.  "Being edited" does not necessarily mean that a user is typing; if a field (for example, a TextField object) has the application's global Text object acting in its place as first responder, then the field is considered as being edited. This method is invoked automatically from stringValue, intValue, and other similar methods, so that a partially edited field's actual value will be correctly returned by those methods.  Returns self.

This method doesn't end editing; to do that, invoke Window's endEditingFor: or abortEditing.

See also:  endEditingFor: (Window), abortEditing



write:
write:(NXTypedStream *)stream

Writes the Control to the typed stream stream.

See also:  read: