// // NJRLabeledImageCell.m // HostLauncher // // Created by nicholas on Wed Aug 01 2001. // Copyright (c) 2001 Nicholas Riley. All rights reserved. // /* F-Script Anywhere is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. F-Script Anywhere is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with F-Script Anywhere; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "NJRLabeledImageCell.h" #import "NSString-NJRExtensions.h" const static float LEFT_PADDING = 3; @implementation NJRLabeledImageCell + (NJRLabeledImageCell *)cell { return [[[self alloc] init] autorelease]; } - (void)dealloc { [image release]; [imageCacheSource release]; image = nil; [super dealloc]; } - copyWithZone:(NSZone *)zone { NJRLabeledImageCell *cell = [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; } - (void)setImageCacheSource:(id)aSource { if (aSource != imageCacheSource) { [imageCacheSource release]; imageCacheSource = [aSource retain]; } } - (NSRect)imageFrameForCellFrame:(NSRect)cellFrame { if (image != nil) { NSRect imageFrame; imageFrame.size = [image size]; imageFrame.origin = cellFrame.origin; imageFrame.origin.x += LEFT_PADDING; imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2); return imageFrame; } 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, LEFT_PADDING + [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, LEFT_PADDING + [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; NSImageRep *preferredRep, *rep; imageSize = NSMakeSize(cellFrame.size.height - 1, cellFrame.size.height - 1); preferredRep = [[[imageCacheSource cachedImage] representations] objectAtIndex: 0]; if (preferredRep != nil && abs([preferredRep size].width - imageSize.width) < 1 && abs([preferredRep size].height != imageSize.height) < 1) { [self setImage: [imageCacheSource cachedImage]]; // FSALog(@"%@ accepting cached image: %@", [self stringValue], preferredRep); } else { NSArray *imageReps = [image representations]; int i, repCount = [imageReps count]; NSSize repSize; preferredRep = [imageReps objectAtIndex: 0]; // FSALog(@"%@ rejecting cached image: %@", [self stringValue], preferredRep); for (i = 1 ; i < repCount ; i++) { rep = [imageReps objectAtIndex: i]; repSize = [rep size]; if (repSize.width == imageSize.width && repSize.height == imageSize.height) { preferredRep = rep; break; } if (repSize.width >= imageSize.width || repSize.height >= imageSize.height) { // pick the smallest of the larger representations if (repSize.width <= [preferredRep size].width || repSize.height <= [preferredRep size].height) preferredRep = rep; } else { // or the largest of the smaller representations if (repSize.width >= [preferredRep size].width || repSize.height >= [preferredRep size].height) preferredRep = rep; } } /* // Working code as of OS X 10.0.4; this breaks in 10.1 for (i = repCount - 1 ; i >= 0 ; i--) { rep = [imageReps objectAtIndex: i]; if (rep != preferredRep) { [image removeRepresentation: rep]; } } // End working code */ // Begin workaround code for bug in OS X 10.1 (removeRepresentation: has no effect) if ([preferredRep size].width > imageSize.width || [preferredRep size].height > imageSize.height) { NSImage *scaledImage = [[NSImage alloc] initWithSize: imageSize]; NSRect rect = { NSZeroPoint, imageSize }; FSALog(@"rescaling %@", [self stringValue]); [scaledImage setFlipped: [controlView isFlipped]]; // XXX this works, but is correct? [scaledImage lockFocus]; [preferredRep drawInRect: rect]; [scaledImage unlockFocus]; [image release]; image = scaledImage; } else if (repCount > 1) { NSImage *sizedImage = [[NSImage alloc] initWithSize: [preferredRep size]]; [sizedImage addRepresentation: preferredRep]; [image release]; image = sizedImage; } // End workaround code } NSDivideRect(cellFrame, &imageFrame, &cellFrame, LEFT_PADDING + imageSize.width, NSMinXEdge); if ([self drawsBackground]) { [[self backgroundColor] set]; NSRectFill(imageFrame); } imageFrame.origin.x += LEFT_PADDING; imageFrame.size = imageSize; imageFrame.origin.y += ceil((cellFrame.size.height + ([controlView isFlipped] ? -1 : 1) * imageFrame.size.height - 2) / 2); if ([image isFlipped] != [controlView isFlipped]) [image setFlipped: [controlView isFlipped]]; [image drawInRect: imageFrame fromRect: NSOffsetRect(imageFrame, -imageFrame.origin.x, -imageFrame.origin.y) operation: NSCompositeSourceOver fraction: 1.0]; [imageCacheSource setCachedImage: image]; } [self setAttributedStringValue: [[self stringValue] asAttributedStringTruncatedToWidth: cellFrame.size.width - 4]]; [self setImageCacheSource: nil]; // without this, we crash (multiple cells get created!) [super drawWithFrame: cellFrame inView: controlView]; } - (NSSize)cellSize { NSSize cellSize = [super cellSize]; cellSize.width += (image ? [image size].width : 0) + LEFT_PADDING; return cellSize; } @end