BSLabeledIconCell
Language: Objective-C, Author: Michele Balistreri
License: Public domain
An NSTextFieldCell subclass which displays both an image and a label. It can be used for example in file listing, inside an NSTableView or NSOutlineView to show both the icon and the name of a file.
BSLabeledIconCell source preview
#import "BSLabeledIconCell.h" @implementation BSLabeledIconCell - (void)dealloc { [image release]; image = nil; [super dealloc]; } - (id)copyWithZone:(NSZone *)zone { BSLabeledIconCell *cell = (BSLabeledIconCell *)[super copyWithZone:zone]; cell->image = [image retain]; return cell; } - (void)setImage:(NSImage *)anImage { if (anImage != image) { [image release]; image = [anImage retain]; } } - (NSImage *)image { return image; } - (NSRect)imageFrameForCellFrame:(NSRect)cellFrame { if (image != nil) { NSRect imageFrame; imageFrame.size = [image size]; imageFrame.origin = cellFrame.origin; imageFrame.origin.x += 3; imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); return imageFrame; } else return NSZeroRect; } - (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent { NSRect textFrame, imageFrame; NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent]; } - (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength { NSRect textFrame, imageFrame; NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge); [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength]; } - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { if (image != nil) { NSSize imageSize; NSRect imageFrame; imageSize = [image size]; NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge); if ([self drawsBackground]) { [[self backgroundColor] set]; NSRectFill(imageFrame); } imageFrame.origin.x += 3; imageFrame.size = imageSize; if ([controlView isFlipped]) { imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2); } else { imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); } [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver]; cellFrame.origin.x += 3; cellFrame.size.width -= 3; cellFrame.origin.y += ceil((imageFrame.size.height / 2) - ([[self font] defaultLineHeightForFont] / 2)); cellFrame.size.height -= ceil((imageFrame.size.height / 2) - ([[self font] defaultLineHeightForFont] / 2)); } if([self isHighlighted] && ![[self highlightColorWithFrame:cellFrame inView:controlView] isEqual:[NSColor secondarySelectedControlColor]]) { NSMutableAttributedString *string = [[[NSMutableAttributedString alloc] initWithString:[self objectValue]] autorelease]; [string addAttribute:NSForegroundColorAttributeName value:[NSColor whiteColor] range:NSMakeRange(0,[string length])]; [self setObjectValue:string]; } [super drawWithFrame:cellFrame inView:controlView]; } - (NSSize)cellSize { NSSize cellSize = [super cellSize]; cellSize.width += (image ? [image size].width : 0) + 3; return cellSize; } @end
BSLabeledIconCell header preview
#import <Cocoa/Cocoa.h> @interface BSLabeledIconCell : NSTextFieldCell { NSImage *image; } - (void)setImage:(NSImage *)anImage; - (NSImage *)image; - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; - (NSSize)cellSize; @endDownload Archive
Compatible with:
- Mac OS X 10.3
- Mac OS X 10.4 PPC
- Mac OS X 10.4 Intel
- Mac OS X 10.5 PPC
- Mac OS X 10.5 Intel

1. Question: Is it correct to set the cell-image implementing the following NSTableView delegate-method:
- (void)tableView:(NSTableView *)aTableView
willDisplayCell:(id)aCell
forTableColumn:(NSTableColumn *)aTableColumn
row:(NSInteger)rowIndex
{
BSLabeledIconCell* cell = aCell;
if ([cell image] == nil) {
NSWorkspace* ws = [NSWorkspace sharedWorkspace];
NSString* path =[filepaths objectAtIndex: rowIndex];
NSImage* icon = [ws iconForFile: path];
[cell setImage: icon];
}
}
2. Unfortunately, neither image nor text are resized to fit the row's height. This results in overlapping/cropped file icons and names. Could you fix this?
Anyway, thank you for sharing your code.
Reiner