#import "DWTableView.h"
#import "NSObjectExtensions.h"


@implementation DWTableView

/* Become 1st Responder */

    - (BOOL) becomeFirstResponder; {
        [self postNotificationAboutSelf: DWTableViewFirstResponderNotification];
        return [super becomeFirstResponder];
    }


#pragma mark -
/* nextKey chain */

    - (NSView*) nextValidKeyView; {
        if ([self delegate] != self && [[self delegate] respondsToSelector: @selector(nextValidKeyView)]) {
            return [[self delegate] nextValidKeyView];
        } else {
            return [super nextValidKeyView];
        }
    }

    - (NSView*) previousValidKeyView; {
        if ([self delegate] != self && [[self delegate] respondsToSelector: @selector(previousValidKeyView)]) {
            return [[self delegate] previousValidKeyView];
        } else {
            return [super previousValidKeyView];
        }
    }
    

#pragma mark -
/* Keydown Override */

    - (BOOL) tryToPerformSelector: (SEL) theSelector; 
    {
        /* self */

        if ([self respondsToSelector: theSelector]) {
            [self performSelector: theSelector withObject: nil];
            return YES;
        }

        /* delegate */
        
        if ([[self delegate] respondsToSelector: theSelector]) {
            [[self delegate] performSelector: theSelector withObject: nil];
            return YES;
        }

        return NO;
    }

    - (void) keyDown: (id) event; 
    {
        unsigned short kc = [event keyCode];
        
        //NSLog(@"%i", kc);

        if (kc == 51 || kc == 117) {	/* delete */
            if ([self tryToPerformSelector: @selector(deleteKeyPressed)]) 
                return;
        }
            
        if (kc == 36 || kc == 76) {	/* enter */
            if ([self tryToPerformSelector: @selector(enterKeyPressed)]) 
                return;
        }
        
        if (kc == 53) {			/* esc */
            if ([self tryToPerformSelector: @selector(escKeyPressed)]) 
                return;
        }
        
        if (kc == 123) {		/* <- */
            if ([self tryToPerformSelector: @selector(leftKeyPressed)]) 
                return;
        }

        if (kc == 124) {		/* -> */
            if ([self tryToPerformSelector: @selector(rightKeyPressed)]) 
                return;
        }
        
        if (kc == 49) {			/* space */
            if ([self tryToPerformSelector: @selector(spaceKeyPressed)]) 
                return;
        }
    
        if (kc == 115) {		/* home */
            if ([self tryToPerformSelector: @selector(homeKeyPressed)]) 
                return;
        }
        
        if (kc == 119) {		/* end */
            if ([self tryToPerformSelector: @selector(endKeyPressed)]) 
                return;
        }
    
        [super keyDown: event];
    }
    
    - (void) homeKeyPressed; {
        [self scrollRowToVisible: 0];
    }
    
    - (void) endKeyPressed; {
        [self scrollRowToVisible: [self numberOfRows]-1];
    }

    - (void) escKeyPressed; {
        [self deselectAll: self];
    }

    - (id) menuForEvent: (NSEvent*) theEvent; 
    {
        if ([self delegate] != self && [[self delegate] respondsToSelector: @selector(menuForEvent:)])
            return [[self delegate] menuForEvent: theEvent];
        else
            return [super menuForEvent: theEvent];
    }


#pragma mark -
/* rectOfRow override */

    /* this delivers a 150+% speed improvement over the default implementation */
    
    /*
    NSRect rectOfRow(NSTableView* view, int row) {
        float h = view->_rowHeight + 2.0f;
        return (NSRect) {
            {0.0f, row * h},
            {view->_frame.size.width, h}
        };
    }
    */
    
    - (NSRect) rectOfRow: (int) row; 
    {
        /* dangerous! (private variables) */
        
        /*
        NSRect frame = [self frame];
        float h = [self rowHeight] + 2;
        */

        #define frame _frame
        float h = _rowHeight + 2.0f;
        
        return (NSRect) {
            {0.0f, row * h},
            {frame.size.width, h}
        };
        #undef frame
    }
    

#pragma mark -
/* Resizing */
    
    - (BOOL) isOpaque; {
        return YES;
    }

    - (BOOL) _wantsLiveResizeToUseCachedImage; {
        return NO;
    }

    - (BOOL) _shouldLiveResizeUseCachedImage; {
        return NO;
    }
    
    - (void) noteNumberOfRowsChanged; {
        if ([self window]) [super noteNumberOfRowsChanged];
    }

@end
