//************************************************************************
//
//	OICNSTableColumn.m
//
//	by Juergen Moellenhoff <jm@oic.de>		
//
//
//	This code is supplied "as is" the author makes no warranty as to its 
//	suitability for any purpose.  This code is free and may be distributed 
//	in accordance with the terms of the:
//		
//			GNU GENERAL PUBLIC LICENSE
//			Version 2, June 1991
//			copyright (C) 1989, 1991 Free Software Foundation, Inc.
// 			675 Mass Ave, Cambridge, MA 02139, USA
//
//************************************************************************

#import "OICNSTableColumn.h"
#import "OICNSTableHeaderCell.h"
#import "OICNSTableViewPrivate.h"

#import <EOInterface/EOInterface.h>

#define	OICNSTABLECOLUMN_CURRENT_VERSION	2

// 
// The NSTableColumn use the NSCoding protocol, but
// NeXT has forgotten to declare it. So I get no warnings 
// from the compiler.
//
@interface NSTableColumn(NSTableColumnNSCodingMethods)

- (id)initWithCoder:(NSCoder *)aDecoder;
- (void)encodeWithCoder:(NSCoder *)aCoder;

@end

//
// The "real" class :-)
//
@implementation OICNSTableColumn

//
// Private Methods
//
+ (OICNSTableHeaderCell *)_createNewHeaderCell:(id)oldCell
{
	OICNSTableHeaderCell	*newCell;

	newCell = [[OICNSTableHeaderCell alloc] init];
	[newCell setBezeled:[oldCell isBezeled]];
	[newCell setBordered:[oldCell isBordered]];
	[newCell setTextColor:[oldCell textColor]];
	[newCell setBackgroundColor:[oldCell backgroundColor]];
	[newCell setFont:[oldCell font]];
	[newCell setObjectValue:[oldCell objectValue]];

	return [newCell autorelease];
}

//
// Public methods
//

//
// This bumps the class version so that we can compatibly read
// old objects out of an archive.
//
+ (void)initialize 
{
	if (self == [OICNSTableColumn class]) 
		[OICNSTableColumn setVersion:OICNSTABLECOLUMN_CURRENT_VERSION];
}

//
// Init
//
- initWithIdentifier:(id)identifier 
{
	// Call to super
	[super initWithIdentifier:identifier];

	// Replace the headerCell with a new (my own)
	// headerCell, but try to copy the "outfit" 
	// of the old headerCell.
	[self setHeaderCell:[OICNSTableColumn _createNewHeaderCell:[self headerCell]]];

	// Set the default sort order
	[self setOrdering:NSOrderedSame];

	// Sort order case sensitive 
	[self setCaseInsensitive:NO];

	return self;
}

//
// NSCoding protocol
//
- (id)initWithCoder:(NSCoder *)aDecoder
{
	NSComparisonResult	tempOrdering;

	[super initWithCoder:aDecoder];

	[aDecoder decodeValueOfObjCType:@encode(typeof(tempOrdering)) at:&tempOrdering];

	if ([aDecoder versionForClassName:@"OICNSTableColumn"] == OICNSTABLECOLUMN_CURRENT_VERSION)
		[aDecoder decodeValueOfObjCType:@encode(typeof(_caseInsensitive)) at:&_caseInsensitive];
	else
		_caseInsensitive = NO;

	[self setOrdering:tempOrdering];

	return self;
}

//
// NSCoding protocol
//
- (void)encodeWithCoder:(NSCoder *)aCoder
{
	[super encodeWithCoder:aCoder];

	[aCoder encodeValueOfObjCType:@encode(typeof(_ordering)) at:&_ordering];
	[aCoder encodeValueOfObjCType:@encode(typeof(_caseInsensitive)) at:&_caseInsensitive];
}

//
// NSCopying protocol
//
- copyWithZone:(NSZone *)z
{
	OICNSTableColumn	*theCopy;
	
	theCopy = [[OICNSTableView _createNewTableColumn:self] retain];

	[theCopy setHeaderCell:[[[self headerCell] copyWithZone:z] autorelease]];
	theCopy->_caseInsensitive = _caseInsensitive;
	[theCopy setOrdering:[self ordering]];

	return theCopy;
}

//
// Update the sort order after a unarchiving from a nib file
//
- (void)awakeFromNib
{
	if ([[self superclass] instancesRespondToSelector:@selector(awakeFromNib)]) 
        [super awakeFromNib];

	// Update the sort order in 
	// all objects that need the sort order.
	[self setOrdering:[self ordering]];
}

//
// Get/Set methods
//
- (void)setOrdering:(NSComparisonResult)newOrdering
{
	_ordering = newOrdering;

	// Update the sort order only when the headerCell responds to
	// setOrdering:
	if ([[self headerCell] respondsToSelector:@selector(setOrdering:)])
	{
		[[self headerCell] setOrdering:_ordering];
		[[[self tableView] headerView] setNeedsDisplay:YES];
	}

	// Update the sort order of the EOColumnAssociation, but do this
	// only when the identifier of the NSTableColumn is a EOColumnAssociation.
    if ([[self identifier] isKindOfClass:[EOColumnAssociation class]])
    {
    SEL	sortingSelector;

        switch(_ordering)
        {
        case NSOrderedAscending:
            if ([self isCaseInsensitive])
				sortingSelector = EOCompareCaseInsensitiveAscending;
			else
				sortingSelector = EOCompareAscending;
            break;
        case NSOrderedDescending:
            if ([self isCaseInsensitive])
 				sortingSelector = EOCompareCaseInsensitiveDescending;
			else
				sortingSelector = EOCompareDescending;
            break;
		case NSOrderedSame:
		default:
			sortingSelector = (SEL)nil;
			break;
        }

		// Force a refresh of the display, too.
        [[self identifier] setSortingSelector:sortingSelector];
    }
}

- (NSComparisonResult)ordering
{
	return _ordering;
}

- (void)setCaseInsensitive:(BOOL)flag
{
	_caseInsensitive = flag;

	if ([self ordering] == NSOrderedSame)
		return;

	// Update the sort order of the EOColumnAssociation
	[self setOrdering:[self ordering]];
}

- (BOOL)isCaseInsensitive
{
	return _caseInsensitive;
}

//
// Method from NSTableColumn
//
- (void)setHeaderCell:(id)aCell
{
	// Call to super
	[super setHeaderCell:aCell];

	// Update the sort order only when the headerCell responds to
	// setOrdering:
	if ([[self headerCell] respondsToSelector:@selector(setOrdering:)])
		[[self headerCell] setOrdering:[self ordering]];
}

@end

//
// Add ons....
//

//
// This is a private method of the class EOTableViewAssociation.
// This method reloads the sort order and updates the display
//
@interface EOTableViewAssociation (C_OIC_EOTableViewAssociationPrivateMethods)

- (void)setSortOrderingByColumnOrder;

@end

//
// With this workaround the refresh of the 
// sort order works in EOF 2.0, too. 
// Without it works only for EOF 2.1
//
@implementation EOColumnAssociation (C_OIC_EOColumnAssociation)

- (void)setSortingSelector:(SEL)newSelector 
{
	_sortingSelector = newSelector;

	// Refresh sort order
	[[[[self object] tableView] dataSource] setSortOrderingByColumnOrder];
}

@end

//
// If the dataCell is an NSImageCell object than the 
// EOColumnAssociation sends a - compare: to it, but the
// contents of the NSImageCell is an NSImage and a NSImage 
// object does not recognize the selector - compare:.
// So this is a quick an dirty workaround for this problem...
//
@implementation NSImage(C_OIC_NSImageAdds)

- (NSComparisonResult)compare:(NSImage *)anImage
{
	if (([self name] == nil) || ([anImage name] == nil))
		return NSOrderedSame;

	return [[self name] compare:[anImage name]];
}

@end
