#pragma .h #import <AppKit/NSMatrix.h>
#pragma .h #import "IKCell.h"

#import <AppKit/AppKit.h>
#import <InterfaceBuilder/InterfaceBuilder.h>

#import "iconkit.h"

@implementation IKIconPath:NSMatrix
{
	IKCell	*current;
	IKCell	*last;
        BOOL    draggingEntered;
}

- initWithFrame:(NSRect)frameRect
{
    if ((self = [self initWithFrame:frameRect mode:NSRadioModeMatrix cellClass:[IKCell  class] numberOfRows:1 numberOfColumns:1]) != nil) {
        [self  setCellSize:frameRect.size];
        [self sizeToCells];
        draggingEntered = NO;
    }
    return self;
}

- initWithFrame:(NSRect)frameRect mode:(int)aMode prototype:aCell numberOfRows:(int)rows numberOfColumns:(int)cols
{
    if ((self = [self initWithFrame:frameRect mode:aMode cellClass:[IKCell  class] numberOfRows:rows  numberOfColumns:cols]) != nil) {
        [self setPrototype:aCell];
        draggingEntered = NO;
    }
    return self;
}

- initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:class numberOfRows:(int)rows numberOfColumns:(int)cols
{
    NSSize zero = { 0, 0 };

    if ((self = [super initWithFrame:frameRect mode:aMode cellClass:class numberOfRows:rows numberOfColumns:cols]) != nil) {
        [self setBackgroundColor:[NSColor lightGrayColor]];
        [self setCellSize:zero];
        [self setIntercellSpacing:zero];
        [self setAllowsEmptySelection:NO];
        draggingEntered = NO;
    }
    return self;
}

- (void)doAwake
{
    draggingEntered = NO;
    [self setCellBackgroundColor:[NSColor lightGrayColor]];
}

- awakeAfterUsingCoder:(NSCoder *)aDecoder
{
    [self doAwake];
    return self;
}

- (void)mouseDown:(NSEvent *)event 
{
    NSPoint	where = [event locationInWindow];
    NSRect	cellFrame;
    int		hit, row, col;
    id		aCell;

    where = [self convertPoint:where fromView:nil];
    [self getRow:&row column:&col forPoint:where];
    aCell = [self cellAtRow:row column:col];
    cellFrame = [self cellFrameAtRow:row column:col];
    hit = [aCell hitPart:&where inRect:&cellFrame];

    if ((hit == IK_ICONPART) && [aCell isDraggable] && !([event modifierFlags] & (NSShiftKeyMask | NSAlternateKeyMask))) {
        if (aCell == [self selectedCell]) {
            [[self window] makeFirstResponder:self];
        } else {
            [self endEditing];
        }	
        [self selectCell:aCell];
        current = last = nil;
        [aCell dragIcon:event inRect:&cellFrame ofView:self];

        if ([event clickCount] > 1) {
            [self sendDoubleAction];
        } else {
            [self sendAction];
        }
    } else if ((hit == IK_TITLEPART) && [aCell isEditable] && [aCell state]) {
        [aCell editTitle:event  inRect:&cellFrame  ofView:self];
    } else {
        if (aCell == [self selectedCell]) {
            [[self window] makeFirstResponder:self];
        } else {
            [self  endEditing];
        }
        [super mouseDown:event];
    }
    [[self window] invalidateCursorRectsForView:self];
}

- (BOOL) shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent
{
    return YES;
}

- editCell:theCell
{
    int	row, col;

    if ([self  getRow:&row column:&col ofCell:theCell]) {
        [self  editCellAt:row :col];
    }
    return self;
}

- editCellAt:(int) row  :(int) col
{
    NSRect cellFrame = [self cellFrameAtRow:row column:col];
    [[self cellAtRow:row column:col] editTitle:NULL inRect:&cellFrame ofView:self];
    return self;
}

- (void)endEditing
{
    NSRect editorFrame;
    id     editor = [[self window] fieldEditor:NO forObject:self];

    if (editor && [[self cells] indexOfObject:[editor delegate]] != NSNotFound) {
        editorFrame = [editor frame];
        [[self window] endEditingFor:self];
        [self displayRect:editorFrame];
    }
}

- (BOOL)abortEditing
{
    return NO;
}

- (void)resetCursorRects
{
    NSRect title;
    id     editor = [[self window] fieldEditor:NO forObject:self],
           editingCell = [editor delegate],
           selection = [self selectedCells],
           theCell;
    int    row, col, i;

    i = [selection  count];
    while (i--) {
        if ([theCell = [selection objectAtIndex:i] isEditable] && theCell != editingCell) {
            [self  getRow:&row  column:&col  ofCell:theCell];
            title = [self cellFrameAtRow:row column:col];
            title = [theCell titleRectForBounds:title];
            [self addCursorRect:title cursor:[NSCursor IBeamCursor]];
        }
    }
    if ([[self cells] indexOfObject:editingCell] != NSNotFound) {
        title = [editor frame];
        [self addCursorRect:title cursor:[NSCursor IBeamCursor]];
    }
}

- (void)drawCellInside:(NSCell *)theCell
{
    int row, col;

    [self getRow:&row column:&col ofCell:theCell];
    [self drawCellAtRow:row column:col];
}

- (NSArray *)selectedCells
{
    int	i, j;
    id	aCell;
    id  selection = [NSMutableArray array];

    for (i = 0; i < _numRows; i++) {
        for (j = 0; j < _numCols; j++) {
            aCell = [self cellAtRow:i column:j];
            if ([aCell state] != 0)
                [selection addObject:aCell];
        }
    }
    return selection;
}

- (void)setCellSize:(NSSize)size
{
    id	editingCell = [[[self window] fieldEditor:NO forObject:self]  delegate];

    [self  endEditing];
    [super setCellSize:size];
    if ([[self cells] indexOfObject:editingCell] != NSNotFound) {
        [self  editCell:editingCell];
    }
}

- (void)setIntercellSpacing:(NSSize)size
{
    id	editingCell = [[[self window] fieldEditor:NO forObject:self]  delegate];

    [self  endEditing];
    [super setIntercellSpacing:size];
    if ([[self cells] indexOfObject:editingCell] != NSNotFound) {
        [self  editCell:editingCell];
    }
}

- (void)setFrameSize:(NSSize)_newSize
{
	id	editingCell = [[[self window] fieldEditor:NO forObject:self]  delegate];

	[self  endEditing];
	[super setFrameSize:(NSSize)_newSize];
	if ([[self cells] indexOfObject:editingCell] != NSNotFound) {
		[self  editCell:editingCell];
	}
}

- cellWithDelegate:delegate
{
    id		theCell;
    int		i;

    for (i = 0; i < [[self cells] count]; i++) {
        if ([theCell = [[self cells] objectAtIndex:i]  delegate] == delegate) {
            return theCell;
        }
    }
    return nil;
}

- objectInColumn:(int) n
{
	return [[self cellAtRow:0 column:n]  delegate];
}

- (NSString *)stringValue
{
    id delegate = [[self selectedCell]  delegate];

    return [delegate respondsToSelector:@selector(path)] ? [delegate  path] : [super stringValue];
}

- (unsigned int) draggingSourceOperationMaskForLocal:(BOOL) isLocal
{
	return NSDragOperationAll;
}

- (unsigned int) draggingEntered:(id <NSDraggingInfo>) sender
{
    if(!draggingEntered) {
        NSLog(@"draggingEntered");
        draggingEntered = YES;
        current = last = nil;
        if ([self enteredNewCell:[sender draggingLocation]])
            return [self cellEntered:sender];
        else
            return NSDragOperationNone;
    } else {
        return [self draggingUpdated:sender];
    }
}

- (unsigned int) draggingUpdated:(id <NSDraggingInfo>) sender
{
    NSLog(@"draggingUpdated");
    if ([self enteredNewCell:[sender draggingLocation]]) {
        if (last)
            [self cellExited:sender];
        return [self cellEntered:sender];
    } else {
        return current ? [self cellUpdated:sender] : [super  draggingUpdated:sender];
    }
}

- (void)draggingExited:(id <NSDraggingInfo>)sender
{
    NSLog(@"draggingExited");
    draggingEntered = NO;
    last = current;
    [self cellExited:sender];
}

- (BOOL)enteredNewCell:(NSPoint) where
{
    int	row, col;
    id	new;

    where = [self convertPoint:where fromView:nil];
    [self getRow:&row column:&col forPoint:where];
    new = [self cellAtRow:row column:col];
    if (new != current)	{
        last = current;
        current = new;
        return YES;
    } else {
        return NO;
    }
}

- (unsigned int) cellEntered:(id <NSDraggingInfo>) sender
{
    unsigned int op = NSDragOperationNone;
    if(current) {
        id delegate = [current  delegate];

        if (	delegate
             &&	[current isDragAccepting]
             &&	[delegate respondsToSelector:@selector(draggingEntered:)]
             &&	((op = [delegate  draggingEntered:sender]) != NSDragOperationNone)) {
            [current setImage:[delegate acceptingDragImage]];
            [self drawCell:current];
        } else
            NSLog(@"current set to nil");
            current = nil;
    }
    return op;
}

- (unsigned int) cellUpdated:(id <NSDraggingInfo>) sender
{
    unsigned int op = NSDragOperationNone;
    if(current) {
        id delegate = [current delegate];
        if(delegate && [delegate respondsToSelector:@selector(draggingUpdated:)]) {
            op = [delegate draggingUpdated:sender];
        } else {
            op = [super draggingUpdated:sender];
        }
    }
    return op;
}

- (void)cellExited:(id <NSDraggingInfo>) sender
{
    if(last) {
        id delegate = [last delegate];

        if (delegate && [delegate respondsToSelector:@selector(draggingExited)]) {
            [delegate draggingExited:sender];
        }
        [last setImage:[delegate image]];
        [self drawCell:last];
    }
}

- (BOOL) prepareForDragOperation:(id <NSDraggingInfo>) sender
{
    id	delegate = [current  delegate];
    NSLog(@"prepareForDragOperation");

    [current  setImage:[delegate  image]];
    [self drawCell:current];

    return [delegate  respondsToSelector:@selector(prepareForDragOperation:)] ?
        [delegate  prepareForDragOperation:sender]:
        YES;
}

- (BOOL) performDragOperation:(id <NSDraggingInfo>) sender
{
    id	delegate = [current  delegate];

    return [delegate  respondsToSelector:@selector(performDragOperation:)] ?
        [delegate  performDragOperation:sender]:
        NO;
}

- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
    id	delegate = [current  delegate];

    return [delegate  respondsToSelector:@selector(concludeDragOperation:)] ?
        [delegate concludeDragOperation:sender]:
        nil;
}

@end
