This article contains miscellaneous tips and examples for manipulating cells and controls.
Setting the Size of a Cell or Control
Drawing a Focus Ring Inside a Cell's Bounds
Positioning an Image Within a Cell
To set the size of a cell (and any enclosing single-cell control) to an optimum size conforming with the human interface guidelines, do the following:
If the cell contains text, set the font of the text to be consistent with one of the three standard sizes: regular, small, and mini. To do this use the NSFont class method systemFontSizeForControlSize:
. The argument to this method is an NSControlSize
constant declared by the NSControl class.
float fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize]; |
NSCell *theCell = [theControl cell]; |
NSFont *theFont = [NSFont fontWithName:[[theCell font] fontName] size:fontSize]; |
[theCell setFont:theFont]; |
Set the control size to the same size as given for the font size, using the same constant. Use the NSControl setControlSize:
method.
[theCell setControlSize:NSMiniControlSize]; |
Finally, send sizeToFit
to the control to trim the extra width.
[theControl sizeToFit]; |
The NSSetFocusRingStyle
sets the style that a focus ring will be drawn in the next time you fill a bezier path. It takes a constant of type of NSFocusRingPlacement
to tell the Application Kit to draw the focus ring over an image, under text, or (when neither text or image is a consideration) around a shape. You can use this function with a constant of NSFocusRingOnly
to draw a focus ring just inside a cell's bounds.
Listing 1 shows how you draw such a focus ring. It requires you to override the NSCell drawWithFrame:inView:
. In this method, if the cell is supposed to draw evidence of first-responder status, set the rectangle for the focus ring, call NSSetFocusRingStyle
with an argument of NSFocusRingOnly
, and then create and fill a bezier path defining that rectangle. Filling in this case simply draws the ring.
Note: This technique requires you to subclass a cell class. See "“Subclassing NSCell”" for information.
Listing 1 Drawing a focus ring just inside a cell's bounds
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { |
// other stuff might happen here |
if ([self showsFirstResponder]) { |
// showsFirstResponder is set for us by the NSControl that is drawing us. |
NSRect focusRingFrame = cellFrame; |
focusRingFrame.size.height -= 2.0; |
[NSGraphicsContext saveGraphicsState]; |
NSSetFocusRingStyle(NSFocusRingOnly); |
[[NSBezierPath bezierPathWithRect: NSInsetRect(focusRingFrame,4,4)] fill]; |
[NSGraphicsContext restoreGraphicsState]; |
} |
// other stuff might happen here |
} |
If a cell is to display an image instead of (or in addition to) text, you can affect the placement of the image within the cell by overridding the imageRectForBounds:
method, which is declared by both the NSCell and NSMenuItemCell classes. This method returns the rectangle the cell's image is drawn in, which is usually a rectangle slightly offset from the cell's bounds. Listing 2 gives an example.
Note: This technique requires you to subclass a cell class. See "“Subclassing NSCell”" for information.
Listing 2 Centering an image in its cell
In this example, the cell centers the image in the cell. Note that it rounds the return values to the nearest pixel to avoid blurring that drawing with partial pixel offsets may cause. The code also sets the size field of the returned rectangle to the size of the image so that it is correctly drawn in the rectangle (assuming the NSImage object uses drawInRect:fromRect:operation:fraction:
for drawing and not compositeToPoint:operation:
).
© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-10-15)