// Copyright 1997-1999 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 "OAOutlineFormatter.h"

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <OmniBase/OmniBase.h>

#import "OAOutlineEntry.h"
#import "OAOutlineView.h"
#import "NSImage-OAExtensions.h"
#import "NSView-OAExtensions.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniAppKit/Outline.subproj/OAOutlineFormatter.m,v 1.6 1999/03/30 21:26:05 kc Exp $")

@implementation OAOutlineFormatter

static NSImage *collapsed;
static NSImage *expanded;
static NSImage *empty;
static NSSize imageSize;
static NSSize dragPointSize;
static NSImage *dragPoint;

+ (void)initialize
{
    static BOOL initialized = NO;
    
    [super initialize];
    if (initialized)
        return;
    initialized = YES;

    collapsed = [[NSImage imageNamed:@"OAOutlineCollapsedEntry" inBundleForClass:self] retain];
    expanded = [[NSImage imageNamed:@"OAOutlineExpandedEntry" inBundleForClass:self] retain];
    empty = [[NSImage imageNamed:@"OAOutlineEmptyEntry" inBundleForClass:self] retain];
    imageSize = [collapsed size];

    dragPoint = [[NSImage imageNamed:@"OAOutlineDraggingPoint" inBundleForClass:self] retain];
    dragPointSize = [dragPoint size];
}

- init
{
    if (![super init])
	return nil;
    entrySpacing = 1.0;
    return self;
}

- (void)setEntrySpacing:(float)spacing;
{
    entrySpacing = spacing;
}

- (float)entrySpacing;
{
    return entrySpacing;
}

- (float)buttonWidth;
{
    return imageSize.width;
}

- (float)entryHeight:(OAOutlineEntry *)anEntry;
{
    return imageSize.height + entrySpacing + 2.0; // 2.0 for an empty pixel on top & bottom
}

- (void)drawSelectionForEntry:(OAOutlineEntry *)anEntry entryRect:(NSRect)rect;
{
    OAOutlineView *outlineView = [anEntry outlineView];
    NSRect frame;

    frame = [outlineView frame];

    frame.origin.y = NSMinY(rect);
    frame.size.height = NSHeight(rect) - entrySpacing;
    [outlineView drawHorizontalSelectionInRect:frame];
}

- (void)drawEntry:(OAOutlineEntry *)anEntry entryRect:(NSRect)rect selected:(BOOL)selected parent:(BOOL)parent hidden:(BOOL)hidden dragging:(BOOL)dragging;
{
    if (dragging) {
	[dragPoint compositeToPoint:NSMakePoint(NSMinX(rect), NSMidY(rect) + dragPointSize.height / 2.0) operation:NSCompositeSourceOver];
    } else {
	if (selected)
            [self drawSelectionForEntry:anEntry entryRect:rect];

        if ([[anEntry outlineView] isHierarchical]) {
            NSImage *image;
            
	    if (parent)
		image = hidden ? collapsed : expanded;
	    else
		image = empty;

            rect.size.height -= entrySpacing;
            [image compositeToPoint:NSMakePoint(NSMinX(rect), NSMidY(rect) + imageSize.height / 2.0) operation:NSCompositeSourceOver];
	}
    }
}

- (void)mouseDown:(NSEvent *)event inRect:(NSRect)rect ofEntry:(OAOutlineEntry *)anEntry;
{
    OAOutlineView *outlineView;

    outlineView = [anEntry outlineView];
    if ([outlineView isSelectable]) {
        if ([event modifierFlags] & NSShiftKeyMask) {
            // If shift is down, toggle selection
            if ([outlineView selection] == anEntry)
                [outlineView setSelectionTo:nil];
            else
                [outlineView setSelectionTo:anEntry];
        } else
            // else just select current item
            [outlineView setSelectionTo:anEntry];
    }
}

- (void)mouseUp:(NSEvent *)event inRect:(NSRect)rect ofEntry:(OAOutlineEntry *)anEntry;
{
    NSPoint point;
    OAOutlineView *outlineView;

    point = [event locationInWindow];
    outlineView = [anEntry outlineView];

    // If we hit the button, toggle whether we show our children
    point = [outlineView convertPoint:point fromView:nil];
    if ([outlineView isHierarchical] && NSMinX(rect) <= point.x && point.x < NSMinX(rect) + imageSize.width)
        [anEntry toggleHidden];
}

- (void)trackMouse:(NSEvent *)mouseDownEvent inRect:(NSRect)rect ofEntry:(OAOutlineEntry *)anEntry;
{
    OAOutlineView *outlineView;
    NSEvent *finalEvent;

    [self mouseDown:mouseDownEvent inRect:rect ofEntry:anEntry];

    outlineView = [anEntry outlineView];
    if (![outlineView shouldStartDragFromMouseDownEvent:mouseDownEvent dragSlop:5 finalEvent:&finalEvent])
        [self mouseUp:mouseDownEvent inRect:rect ofEntry:anEntry];
    else if (!([mouseDownEvent modifierFlags] & NSShiftKeyMask))
        [outlineView dragSublist:anEntry causedByEvent:mouseDownEvent currentEvent:finalEvent];
}

@end
