//
//  tdTableView.m
//  Hootenanny
//
//  Created by Noah Sorscher on 2/5/05.
//  Copyright 2005 __MyCompanyName__. All rights reserved.
//

#import "tdTableView.h"
#import "MHFormatter.h"

@interface NSCell (additions)
//- (int)imageRow;
//- (void)setPictureTime:(BOOL)flag;
@end

@implementation NSCell (additions)
- (void)setWrapsObj:(NSNumber *)flag
{
    [self setWraps:[flag boolValue]];
}
@end

@implementation NSTableHeaderView (rclick)

- (void)rightMouseDown:(NSEvent *)theEvent
{
    if ([[[self tableView] delegate] respondsToSelector:@selector(tableView:headerRightClickWithEvent:)])
        [[[self tableView] delegate] tableView:[self tableView] headerRightClickWithEvent:theEvent];
}

@end


@interface NSTextView (additions)
- (void)setSelectedRangeData:(NSData *)range;
@end

@implementation NSTextView (additions)
- (void)setSelectedRangeData:(NSData *)range
{
    NSRange *p = (NSRange *)[range bytes];
    NSRange r = *p;
    int length = [[self string] length];
    if (r.location > length) r.location = length;
    if (r.location + r.length > length) r.length = length - r.location;
    [self setSelectedRange:r];
}
@end

@interface NSObject (d2)
- (id) delegate2;
@end

@implementation tdTableView

- (void)backSpace
{
    didDelete = YES;
}

- (void)rightMouseDown:(NSEvent *)theEvent
{
    if ([[self delegate] respondsToSelector:@selector(tableView:rightClickWithEvent:)])
        [[self delegate] tableView:self rightClickWithEvent:theEvent];
}

- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
    NSString *chars = [theEvent characters];
    unichar uch = [chars characterAtIndex:0];
    if (uch == 127 && // delete
        [[self window] firstResponder] == self  &&
        !([theEvent modifierFlags] & NSControlKeyMask) &&
        !([theEvent modifierFlags] & NSAlternateKeyMask) &&
        !([theEvent modifierFlags] & NSShiftKeyMask)) {
		if ([theEvent modifierFlags] & NSCommandKeyMask) {
			if ([[self delegate] respondsToSelector:@selector(commandDeleteForTableView:)])
				return [[self delegate] commandDeleteForTableView:self];
		} else {
			if ([[self delegate] respondsToSelector:@selector(deleteForTableView:)])
				return [[self delegate] deleteForTableView:self];
		}
    }/* else if (uch == 3 || uch == 13) { // Enter and Return, respectively
        //NSLog(@"return, %@", [self autosaveName]);
        if (editsOnEnter) {
            [self performSelector:@selector(edit:) withObject:[NSNumber numberWithInt:[self selectedRow]] afterDelay:0];
            //NSLog(@"edit, %@", [self autosaveName]);
            return YES;
        }
    }*/
    return [super performKeyEquivalent:theEvent];
}

- (void) awakeFromNib
{
	partialString = nil;
	textEditVar = YES;
	resizing = NO;
	//[super awakeFromNib];
	//NSLog(@"awake");
	int i, n = [[self tableColumns] count];
	for (i=0;i<n;i++) {
		NSTableColumn *col = [[self tableColumns] objectAtIndex:i];
		//NSLog(@"format column: %@", [col identifier]);
		[[col dataCell] setFormatter:[[MHFormatter alloc] initWithColumn:col]];
		[[col dataCell] setFont:[NSFont systemFontOfSize:[tInit doubleForKey:@"fontSize"]]];
	}
}

- (void)edit:(NSNumber *)column
{
	int col = [column intValue], row = [self editedRow];
    if (row < 0 || row >= [self numberOfRows]) return;
    if ([[self delegate] respondsToSelector:@selector(shouldEditTableColumn:row:)])
        [[self delegate] shouldEditTableColumn:[[self tableColumns] objectAtIndex:col] row:row];
    [self selectRow:row byExtendingSelection:NO];
    int numCols = [[self tableColumns] count];
    if (numCols) {
        if (col >= numCols) col = 0;
        //NSLog(@"lastCol: %d, selRow: %d", lastEditedColumn, [self selectedRow]);
        [self editColumn:col row:row withEvent:nil select:YES];
    }
}
/*
- (int)numberOfRowsInTableView:(NSTableView *)tview
{
    //NSLog(@"numberOfRows");
    return [oldDataSource numberOfRowsInTableView:tview];
}

- (id)tableView:(NSTableView *)tview objectValueForTableColumn:(NSTableColumn *)tcol row:(int)rowIndex
{
	return partialString;
}

- (void)tableView:(NSTableView *)tview setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tcol row:(int)rowIndex
{
	partialString = anObject;
}
*/
- (void)resizeTextView:(NSTextView *)t
{
    int row = [self editedRow], col = [self editedColumn];
    if (row < 0 || row >= [self numberOfRows] || col < 0 || col >= [self numberOfColumns]) return;
    NSString *newValue = [NSString stringWithString:[t string]];
	[curEditedText release];
	curEditedText = [[NSString alloc] initWithString:newValue];
	NSArray *sels = [t selectedRanges];
	NSString *oldValue = [[self dataSource] tableView:self objectValueForTableColumn:[[self tableColumns] objectAtIndex:col] row:row];
	if (!oldValue) oldValue = @"";
	[t setString:oldValue];
	resizing = YES;
	[self edit:[NSNumber numberWithInt:col]];
	resizing = NO;
	//NSLog(@"restore: %@", newValue);
	[t setString:newValue];
	[t setSelectedRanges:sels];
	
	[self setNeedsDisplay:YES];
    //oldDataSource = oldDelegate = nil;
}

- (void)textDidChange:(NSNotification *)aNotification
{
     NSTextView *t = [aNotification object];
    //NSString *class = [t className];
    if (!didDelete && [t respondsToSelector:@selector(delegate2)]) {
        id d = [t delegate2];
        if ([d respondsToSelector:@selector(textDidChange:)])
            [d textDidChange:aNotification];
    }
    didDelete = NO;
	
	
	
    [curEditedText release];
    curEditedText = [[NSString alloc] initWithString:[t string]];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resizeTextView:) object:t];
    [self performSelector:@selector(resizeTextView:) withObject:t afterDelay:1];
	
}
/*
- (void)textDidEndEditing:(NSNotification *)aNotification
{
	if (textEditVar) {
		[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resizeTextView:) object:nil];
		[curEditedText release];
		curEditedText = nil;
		//[[col dataCell] setWraps:NO];
		//[[col dataCell] setScrollable:YES];
	}
}
*/
- (void)setEditsOnEnter:(BOOL)flag
{
    //NSLog(@"set edits: %d, %@", flag, [self autosaveName]);
    //editsOnEnter = flag;
}

- (void)setEditsOnEnterObj:(NSNumber *)flag
{
    //NSLog(@"set edits: %d, %@", [flag boolValue], [self autosaveName]);
    //editsOnEnter = [flag boolValue];
}

- (NSRect)frameOfCellAtColumn:(int)columnIndex row:(int)rowIndex
{
    NSTableColumn *col = [[self tableColumns] objectAtIndex:columnIndex];
    NSRect r = [super frameOfCellAtColumn:columnIndex row:rowIndex];
    //if (!grows /*|| sorting*/) return r;
	int colE = [self editedColumn];
	int rowE = [self editedRow];
	if (colE == -1 || rowE == -1) return r;
	if (colE != columnIndex || rowE != rowIndex) return r;
    //NSCell *cell = [[[self tableColumns] objectAtIndex:columnIndex] dataCellForRow:rowIndex];
    NSString *string = [[self dataSource] tableView:self objectValueForTableColumn:col row:rowIndex];
    //NSLog(@"old: %@", string);
    if (curEditedText && [curEditedText length] > [string length]) {
        string = curEditedText;
        //NSLog(string);
    }
    if (![string isKindOfClass:[NSString class]])
        string = [string description];
	//NSLog(@"frame of string: %@ (cur = %@)", string, curEditedText);
    NSAttributedString *aString = nil;
    if ([string length]) {
        NSAttributedString *displayString = [[col dataCell] attributedStringValue];
        NSDictionary *attributes = [displayString attributesAtIndex:0 effectiveRange:nil];
        aString = [[NSAttributedString alloc] initWithString:string attributes:attributes];
    }
    NSSize s = [self sizeOfString:aString];
    //NSLog (@"old: %g x %g, new: %g x %g", r.size.width, r.size.height, s.width, s.height);
    if (s.width > r.size.width) r.size.width = s.width;
    if (s.height > r.size.height) r.size.height = s.height;
    NSRect frame = [self visibleRect];
    //NSLog(@"%g, %g, %g x %g", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
    if (r.size.width > frame.size.width - 10)
        r.size.width = frame.size.width - 10;
    if (r.size.height > frame.size.height - 10)
        r.size.height = frame.size.height - 10;
    float x = r.origin.x + r.size.width - frame.size.width - frame.origin.x + 5;
    if (x > 0) r.origin.x -= x;
    float y = r.origin.y + r.size.height - frame.size.height - frame.origin.y + 5;
    if (y > 0) r.size.height -= y;
    //NSLog(@"frameOfCell %dx%d: (%gx%g)%gx%g", columnIndex, rowIndex, r.origin.x, r.origin.y, r.size.width, r.size.height);
    return r;
}

- (NSSize)sizeOfString:(NSAttributedString *)string
{
    if (!string || ![string length]) return NSZeroSize;
    int threash = 60;
    NSMutableString *outString = [NSMutableString string];
    int index = 0, tally = 0;
    while (YES) {
        if (index >= [string length])
            break;
        char ch = [[string string] characterAtIndex:index];
        [outString appendFormat:@"%c", ch];
        if (ch == '\n' || ch == '\r')
            tally = 0;
        tally++;
        index++;
        if (tally >= threash) {
            NSRange aRange = [outString rangeOfString:@" " options:NSBackwardsSearch];
            if (aRange.length)
                [outString replaceCharactersInRange:aRange withString:@"\n"];
            tally = 0;
        }
    }
    NSSize s = [[[NSAttributedString alloc] initWithString:outString attributes:[string attributesAtIndex:0 effectiveRange:nil]] size];
    int extra = [string length];
    if (extra > threash) extra = threash;
    s.width += extra;
    s.height += 5;
    return s;
}

- (void)editColumn:(int)columnIndex row:(int)rowIndex withEvent:(NSEvent *)theEvent select:(BOOL)flag
{/*
    //	on beginning editing, we remember which cell is being edited
    if (rowIndex < 0 || rowIndex >= [self numberOfRows] || columnIndex < 0 || columnIndex >= [self numberOfColumns]) return;
    rowFocus = rowIndex;
    colFocus = columnIndex;
    lastEditedColumn = colFocus;*/
    NSCell *cell = [[[self tableColumns] objectAtIndex:columnIndex] dataCell];
    [cell setWraps:YES];
	if (!resizing) {
		[curEditedText release];
		curEditedText = nil;
	}
    //if ([cell respondsToSelector:@selector(setTextColor:)])
    //    [(NSTextFieldCell *)cell setTextColor:[NSColor blackColor]];
    //NSText *aText = [[self window] fieldEditor:YES forObject:nil];
    //[aText setBackgroundColor:[NSColor redColor]];
    [super editColumn:columnIndex row:rowIndex withEvent:theEvent select:flag];
}

- (NSRect)smallFrameOfCellAtColumn:(int)c row:(int)r
{
    return [super frameOfCellAtColumn:c row:r];
}

// ----------------------------------------------------------------------------------------
// Animated Sort support -- from "TableTester" at http://www.gigliwood.com/tabletester/
// ----------------------------------------------------------------------------------------

- (void) setSorting:(BOOL)flag
{
    sorting = flag;
}

/*"	Override NSTableView's method.  Let the delegate determine what the rectangle for a given row is, if that delegate responds to the selector to do so.  If animation is going on, it will probably return a value other than the default.
 "*/
- (NSRect)rectOfRow:(int)rowIndex
{
	NSRect theDefaultRect = [super rectOfRow:rowIndex];
	//NSLog(@"rectOfRow -> %@", [[self delegate] className]);
	//return theDefaultRect;
	if ([[self delegate] respondsToSelector:@selector(tableView:rectOfRow:defaultRect:)])
	{
		//NSLog(@"rightCall");
		return [[self delegate] tableView:self rectOfRow:rowIndex defaultRect:theDefaultRect];
	}
	else
	{
		//NSLog(@"wrongCall");
		return theDefaultRect;
	}
}

/*"	Return the default NSTableView's version of the rectangle for a given row; this method is provided so we can determine the rectangle as if animation weren't happening.
 "*/
- (NSRect)unanimatedRectOfRow:(int)rowIndex
{
	return [super rectOfRow:rowIndex];
}

/*"	Override NSTableView's method.  Let the delegate determine what the range of rows is for a given rectangle, if that delegate responds to the selector to do so.  If animation is going on, it will probably return a value other than the default.
 "*/
- (NSRange)rowsInRect:(NSRect)inRect

{
	NSRange theDefaultRange = [super rowsInRect:inRect];
	//return theDefaultRange;
	if ([[self delegate] respondsToSelector:@selector(tableView:rowsInRect:defaultRange:)])
	{
		return [[self delegate] tableView:self rowsInRect:inRect defaultRange:theDefaultRange];
	}
	else
	{
		return theDefaultRange;
	}
}

// end animated sort support


@end
