//
//  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];
    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;
}

- (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);

		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];
    }
    [self setAttributedStringValue:
        [[self stringValue] asAttributedStringTruncatedToWidth: cellFrame.size.width - 4]];
    [super drawWithFrame: cellFrame inView: controlView];
}

- (NSSize)cellSize {
    NSSize cellSize = [super cellSize];
    cellSize.width += (image ? [image size].width : 0) + LEFT_PADDING;
    return cellSize;
}

@end
