| Index | Submit class | Submit snippet | Submission feed | List |

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;

@end
Download Archive

Compatible with:


Comments

Reiner PIttinger says:

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

Name

Website

Do you hate spammers? (Answer "Yes")