// Copyright 1997-2000 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OHImageCell.h"

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>
#import <OmniAppKit/OmniAppKit.h>
#import <OWF/OWF.h>

// #import "OWController.h"
#import "OHHTMLAnchor.h"
#import "OHHTMLPageView.h"

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniHTML/Cells.subproj/OHImageCell.m,v 1.25 2000/02/03 01:48:19 kc Exp $")

@implementation OHImageCell

static NSImage *genericImage;

+ (void)initialize;
{
    static BOOL initialized = NO;

    [super initialize];
    if (initialized)
	return;
    initialized = YES;

    genericImage = [NSImage imageNamed:@"NotFetched"];
}

// Init and dealloc

- (void)dealloc;
{
    [link removeContainedCell:self];
    [link release];
    [cellImage release];
    [super dealloc];
}


// NSTextAttachment pretend subclass

- (NSFileWrapper *)fileWrapper;
{
    NSFileWrapper *fileWrapper;

    fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:[cellImage TIFFRepresentation]];
    [fileWrapper setPreferredFilename:[NSStringFromClass(isa) stringByAppendingString:@".tiff"]];
    return [fileWrapper autorelease];
}


// OHBasicCell subclass

/*
- (NSSize)contentSizeInLayoutBounds:(NSRect)layoutBounds;
{
    NSSize contentSize;

    contentSize = [super contentSizeInLayoutBounds:layoutBounds];
    // TODO Do we really want a minimum size on image cells?
    // contentSize.width = MAX(8.0, contentSize.width);
    // contentSize.height = MAX(8.0, contentSize.height);
    return contentSize;
}
*/

- (NSSize)totalSizeInLayoutBounds:(NSRect)layoutBounds;
{
    // Casting to float before turning negative because an unsigned -n is a huge positive number.
    return OHInsetSize([super totalSizeInLayoutBounds:layoutBounds], -(float)borderWidth, -(float)borderWidth);
}

- (NSSize)naturalSize;
{
    return naturalSize;
}

- (void)drawRect:(NSRect)drawRect inHTMLView:(OHHTMLView *)htmlView;
{
    if (borderWidth) {
        NSRect contentFrame;

        contentFrame = [self contentFrame];
        if (NSWidth(contentFrame) < 1.0 || NSHeight(contentFrame) < 1.0)
            return;

	[[self borderColor] set];
	NSFrameRectWithWidth(contentFrame, borderWidth);
    }
    
    [self drawInteriorWithFrame:[self contentFrameWithoutBorder] inView:htmlView];
}

- (BOOL)wantsToTrackMouse;
{
    return YES;
}

- (BOOL)trackMouse:(NSEvent *)event inHTMLView:(OHHTMLView *)htmlView;
{
    BOOL startDrag = NO;
    NSEvent *finalEvent = event;

    switch ([event type]) {
        case NSLeftMouseDown:
            startDrag = [htmlView shouldStartDragFromMouseDownEvent:event dragSlop:20.0 finalEvent:&finalEvent];
            if (startDrag)
                [self startDragFromView:htmlView event:event];
            else
                [self userClicked:finalEvent inHTMLView:htmlView];
            return YES;
        case NSRightMouseDown:
            [self userClicked:event inHTMLView:htmlView];
            [htmlView showContextMenuForMouseEvent:event];
            return YES;
        default:
            return NO;
    }
}

- (OHHTMLAnchor *)link;
{
    return link;
}

- (void)userClicked:(NSEvent *)event inHTMLView:(OHHTMLView *)htmlView;
{
    if (!link || ![link address])
	return;

    [link followFromEvent:event];
}


//

- (NSImage *)image;
{
    if (cellImage)
        return [[cellImage retain] autorelease];
    else
        return genericImage;
}

- (void)setImage:(NSImage *)newImage;
{
    if (cellImage != newImage) {
        [cellImage release];
        cellImage = [newImage retain];
    }
    [self setImageSize:[cellImage size]];
}

- (void)setImageSize:(NSSize)newSize;
{
    if (naturalSize.height == newSize.height && naturalSize.width == newSize.width)
	return;
    
    naturalSize = newSize;
    if ((requestedSize.width == 0 || requestedSize.height == 0) // Not overridden by requestedSize
        && (NSWidth(cellFrame) > 0 || NSHeight(cellFrame) > 0)) // Already laid-out once
        [self relayoutCell];
}

- (void)setBorderWidth:(unsigned int)aBorderWidth;
{
    borderWidth = aBorderWidth;
}

- (unsigned int)borderWidth;
{
    return borderWidth;
}

- (NSRect)contentFrameWithoutBorder;
{
    return NSInsetRect([self contentFrame], borderWidth, borderWidth);
}

@end


@implementation OHImageCell (SubclassesOnly)

// Subclass us

- (NSColor *)borderColor;
{
    static NSColor *OHImageCellBorderColor = nil;

    if (!OHImageCellBorderColor) {
        OHImageCellBorderColor = [[[OFUserDefaults sharedUserDefaults] colorForKey:@"OHImageCellBorderColor"] retain];
    }

    return link ? [link color] : OHImageCellBorderColor;
}

- (void)drawInteriorWithFrame:(NSRect)contentFrame inView:(OHHTMLView *)aView;
{
    NSImage *drawImage;

    drawImage = [self image];
    if (drawImage) {
	NS_DURING {
	    NSPoint compositePoint;
	    NSSize realImageSize;

	    realImageSize = [drawImage size];
	    compositePoint.x = NSMidX(contentFrame) - realImageSize.width / 2;
	    compositePoint.y = NSMidY(contentFrame) + realImageSize.height / 2;
	    [drawImage compositeToPoint:compositePoint operation:NSCompositeSourceOver];
            // Ensure all code is executed by Window Server.
#if defined(RHAPSODY) && (OBOperatingSystemMajorVersion > 5)
            [[NSGraphicsContext currentContext] wait];
#else
            [[NSDPSContext currentContext] wait];
#endif
	} NS_HANDLER {
	    [NSApp reportException:localException];
	} NS_ENDHANDLER;
    } else {
        [[NSColor controlShadowColor] set];
	NSFrameRectWithWidth(contentFrame, 1);
    }
}

- (void)startDragFromView:(OHHTMLView *)aView event:(NSEvent *)event;
{
}

@end


@implementation OHImageCell (Private)


- (NSMutableDictionary *)debugDictionary;
{
    NSMutableDictionary *debugDictionary;

    debugDictionary = [super debugDictionary];
    if (link)
	[debugDictionary setObject:link forKey:@"link"];

    return debugDictionary;
}

@end
