DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
How To Display Indeterminate NSProgressIndicator In The NSOutlineView
ImageTextFieldCell.h:
@interface ImageTextFieldCell : NSTextFieldCell {
// An image to display before text label
NSImage *image;
// An array for caching all used indicators
NSMutableArray *indicators;
// Flag of displaying progress indicator
BOOL inProgress;
// Every connected item should have a property called progressIndicator
id item;
}
@property (retain) NSImage *image;
@property (retain) id item;
@property BOOL inProgress;
@end
ImageTextFieldCell.m:
@interface ImageTextFieldCell(Private)
// Creates and auto-releases new progress indicator
- (NSProgressIndicator *)autoreleasedIndicator;
// Utility methods
- (void)drawImageInFrame:(NSRect *)cellFrame view:(NSView *)controlView;
- (void)placeIndicatorInFrame:(NSRect *)cellFrame view:(NSView *)controlView;
@end
@implementation ImageTextFieldCell
@synthesize image;
@synthesize inProgress;
@synthesize item;
// This method is implemented because text cells are defined through the NIB-file
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
indicators = [NSMutableArray new];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
ImageTextFieldCell *cell = [super copyWithZone:zone];
cell->image = [image retain];
cell->inProgress = inProgress;
cell->indicators = [NSMutableArray new];
cell->item = [item retain];
return cell;
}
- (void) dealloc {
[self setImage:nil];
[self setItem:nil];
[indicators release], indicators = nil;
[super dealloc];
}
CGFloat const kSpaceBetweenImageAndText = 2.0f;
- (void)editWithFrame:(NSRect)aRect
inView:(NSView *)controlView
editor:(NSText *)textObj
delegate:(id)anObject
event:(NSEvent *)theEvent {
NSRect imageFrame, textFrame;
NSDivideRect (aRect, &imageFrame, &textFrame,
[image size].width + kSpaceBetweenImageAndText * 2, 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 imageFrame, textFrame;
NSDivideRect(aRect, &imageFrame, &textFrame,
[image size].width + kSpaceBetweenImageAndText * 2, NSMinXEdge);
[super selectWithFrame:textFrame
inView:controlView
editor:textObj
delegate:anObject
start:selStart
length:selLength];
}
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
[self drawImageInFrame:&cellFrame view:controlView];
[self placeIndicatorInFrame:&cellFrame view:controlView];
[super drawWithFrame:cellFrame inView:controlView];
}
#pragma mark -
#pragma mark Helper methods
CGFloat const kWidthOfProgressIndicator = 16.0f;
- (NSProgressIndicator *)autoreleasedIndicator {
NSRect frame = NSMakeRect(0.0f, 0.0f, kWidthOfProgressIndicator, kWidthOfProgressIndicator);
NSProgressIndicator *indicator = [[NSProgressIndicator alloc] initWithFrame:frame];
[indicator setControlSize:NSSmallControlSize];
[indicator setStyle:NSProgressIndicatorSpinningStyle];
[indicator setUsesThreadedAnimation:YES];
return [indicator autorelease];
}
-(void)drawImageInFrame:(NSRect *)cellFrame view:(NSView *)controlView {
if (!image) return;
NSSize imageSize = [image size];
NSRect imageFrame;
NSDivideRect(*cellFrame, &imageFrame, cellFrame,
imageSize.width + kSpaceBetweenImageAndText * 2, NSMinXEdge);
if ([self drawsBackground]) {
[[self backgroundColor] set];
NSRectFill(imageFrame);
}
imageFrame.size = imageSize;
imageFrame.origin.x += kSpaceBetweenImageAndText;
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];
}
- (void)placeIndicatorInFrame:(NSRect *)cellFrame view:(NSView *)controlView {
NSProgressIndicator *indicator = [item valueForKey:@"progressIndicator"];
if (inProgress) {
if (!indicator) {
indicator = [self autoreleasedIndicator];
[indicator startAnimation:nil];
[indicators addObject:indicator];
[item setValue:indicator forKey:@"progressIndicator"];
}
NSRect indicatorFrame;
NSDivideRect(*cellFrame, &indicatorFrame, cellFrame,
kWidthOfProgressIndicator + kSpaceBetweenImageAndText * 2, NSMaxXEdge);
indicatorFrame.size = [indicator frame].size;
indicatorFrame.origin.x += kSpaceBetweenImageAndText;
indicatorFrame.origin.y += ceil(((*cellFrame).size.height - kWidthOfProgressIndicator) / 2);
[indicator setFrame:indicatorFrame];
[controlView addSubview:indicator];
}
else if (indicator) {
[indicator stopAnimation:nil];
[[indicator superview] setNeedsDisplayInRect:[indicator frame]];
[indicator removeFromSuperviewWithoutNeedingDisplay];
[indicators removeObject:indicator];
[item setValue:nil forKey:@"progressIndicator"];
}
}
@end
SidebarViewController.m:
…
- (void)outlineView:(NSOutlineView *)outlineView
willDisplayCell:(id)cell
forTableColumn:(NSTableColumn *)tableColumn
item:(id)item {
id sidebarItem = [item representedObject];
[cell setItem:sidebarItem];
[cell setInProgress:[sidebarItem isHandling]];
if (sidebarItem == searchItem) {
[cell setImage:searchImage];
}
else if (sidebarItem == uploadsItem) {
[cell setImage:uploadsImage];
}
else {
[cell setImage:nil];
}
}
…





