#import "AqBrowserView.h"
#import "AqMetaNode(Actions).h"
#import "AqMetaNode(Drawing).h"
#import "AqMetaTableView.h"
#import "DWColor.h"


@implementation AqMetaTableView

/* Initialization */

    static id white = nil;
    static id secondary = nil;
    static id alternate = nil;

    - (id) initWithFrame: (NSRect) theFrame; {
        self = [super initWithFrame: theFrame];
        if (!white) {
            white     = [DWColor whiteColor];
            alternate = [DWColor alternateSelectedControlColor];
            secondary = [DWColor secondarySelectedControlColor];
        }
        objects = [[NSMutableArray alloc] init];
        [self setDelegate: self];
        [self setAllowsEmptySelection: NO];
        [self setAllowsColumnResizing: NO];
        [self setHeaderView: nil];
        [self setCornerView: nil];
        return self;
    }
    
    - (void) dealloc; {
        [selected release];
        [super dealloc];
    }


#pragma mark -
/* Accessors */

    - (id) objects; {
        return objects;
    }

    - (AqMetaNode*) rootNode; {
        return rootNode;
    }

    - (AqMetaNode*) selectedNode; {
        int row = [self selectedRow];
        if (row >= 0 && (unsigned)row < [objects count]) return [objects objectAtIndex: row];
        else return nil;
    }
    
    - (id) menuForEvent: (id) theEvent; {
        int row = [self rowAtPoint: [theEvent locationInView: self]];
        if (row >= 0 && ![self isRowSelected: row]) {
            [[self window] makeFirstResponder: self];
            [self selectRow: row byExtendingSelection: NO];
        }
        return [[self selectedNode] menuForEvent: theEvent];
    }
    

#pragma mark -
/* Selected Objects */

    /* this is somewhat excessive in scope since only a single node can be selected at any given time, but anyways, this is mostly code take from DWTableController.  So, whatever. */
    
    - (NSArray*) selectedObjects; {
        id o, i, e = [self selectedRowEnumerator];
        id result = [[[NSMutableArray alloc] init] autorelease];
        while ((i = [e nextObject])) {
            o = [objects objectAtIndex: [i intValue]];
            if (o) [result addObject: o];
        }
        return result;
    }

    - (void) saveSelectedObjects; {
        [selected release];
        selected = [[self selectedObjects] retain];
    }
    
    - (void) restoreSelectedObjects; {
        id obj, e = [selected objectEnumerator];
        [self deselectAll: self];
        while ((obj = [e nextObject])) {
            [self selectRow: [objects indexOfObject: obj] byExtendingSelection: NO];
        }
    }


/* Mutators */

    - (void) setRootNode: (id) theNode; {
        rootNode = theNode;
        [theNode sort];
        [self setObjects: [theNode nodes]];
    }

    - (void) setObjects: (id) theObjects; 
    {
        int i, count;

        /* reset old nodes */
        
            count = [objects count];
            for (i=0; i<count; i++) {
                AqMetaNode* node = [objects objectAtIndex: i];
                node->metaView = nil;
            }
                
        /* set array */

            [self saveSelectedObjects];
            //objects = theObjects;
            [objects setArray: theObjects];
            [self restoreSelectedObjects];
            
            [self setNeedsDisplay: YES];

        /* set new nodes */
        
            count = [objects count];
            for (i=0; i<count; i++) {
                AqMetaNode* node = [objects objectAtIndex: i];
                node->metaView = self;
            }
    }

    - (void) setBrowserView: (id) theView; {
        browserView = theView;
    }


#pragma mark -
/* Events */

    - (void) nodeWasAdded; {
        [NSObject cancelPreviousPerformRequestsWithTarget: browserView selector: @selector(updateTables) object: nil];
        [browserView performSelector: @selector(updateTables) withObject: nil afterDelay: 0];
    }


#pragma mark -
/* Draw */

    - (BOOL) isOpaque; {
        return YES;
    }

    - (int) numberOfRows; {
        return [objects count];
    }
    
    - (int) numberOfColumns; {
        return 1;
    }

    - (void) drawRect: (NSRect) rect; 
    {
        int i, count;
        float dy = _rowHeight + 2;
        int dwColorIndex;
        
        /* draw background */
            
            [white set];
            NSRectFill(rect);
    
        /* draw rows */
        
            i = floor(rect.origin.y/dy);
            count = MIN([self numberOfRows], ceil((rect.origin.y + rect.size.height)/dy));
            
            BOOL hasComputedFirstResponder = NO;
            BOOL isFirstResponder = NO;

            for (; i<count; i++) 
            {
                NSRect rowRect = [self rectOfRow: i];
                
                /* draw background, if necessary */
                if ( [self isRowSelected: i] ) {

                    if ( !hasComputedFirstResponder ) {

                        isFirstResponder = [[self window] firstResponder] == self && [[self window] isKeyWindow];
                        hasComputedFirstResponder = YES;

                    }

                    dwColorIndex = (isFirstResponder) ? kDWColorAlternateIndex : kDWColorSecondaryIndex;

                    [(isFirstResponder) ? alternate : secondary set];
                    NSRectFill(rowRect);

                } else {

                    dwColorIndex = kDWColorWhiteIndex;

                }
                
                /* draw the row */
                    
                    AqMetaNode* node = [objects objectAtIndex: i];
                    node->dwColorIndex = dwColorIndex;
                    [node drawWithFrame: rowRect];
            }
    }


#pragma mark -

    - (void) leftKeyPressed; {
        [browserView leftKeyPressed: self];
    }

    - (void) rightKeyPressed; {
        [browserView rightKeyPressed: self];
    }

    - (NSView*) nextValidKeyView; {
        return [browserView nextValidKeyView: self];
    }

    - (NSView*) previousValidKeyView; {
        return [browserView previousValidKeyView: self];
    }

#pragma mark -
    
    - (void) addOrRemoveScroller; {
        id scrollView = [self enclosingScrollView];
        BOOL shouldHaveVerticalScroller = (_frame.size.height > [scrollView documentVisibleRect].size.height);
        if (shouldHaveVerticalScroller ^ [scrollView hasVerticalScroller]) {
            [scrollView setHasVerticalScroller: shouldHaveVerticalScroller];
            [[scrollView contentView] viewFrameChanged: nil];
        }
    }
    
    - (void) tile; {
        [super tile];
        [self addOrRemoveScroller];
    }

    - (NSFocusRingType) focusRingType; {
        return NSFocusRingTypeNone /* 1 */;
    }

@end