//
//  NSTableView+RSAutosaving.m
//  RSCommon
//
//  Created by Daniel Jalkut on 7/21/06.
//  Copyright 2006 Red Sweater Software. All rights reserved.
//
//	Freely licensed under the MIT license. See associated license file for details.
//

#import "NSTableView+RSAutosaving.h"

NSString* kAutosavedColumnWidthKey = @"AutosavedColumnWidth";
NSString* kAutosavedColumnIndexKey = @"AutosavedColumnIndex";

// We implement some methods on other classes as part of the private implementation.
// These are near the end of this file.
@interface NSTableColumn (RSTableViewAutosaving)
- (int) safeResizingMask;
- (void) setSafeResizingMask:(int) maskOrBOOL;
@end

@interface NSDictionary (RSTableViewAutosaving)
- (NSComparisonResult)compareByAutosavedIndex:(NSDictionary *)otherDict;
@end

@implementation NSTableView (RSAutosaving)

- (NSDictionary *) dictionaryForAutosavingLayout
{
	NSMutableDictionary* autoDict = [NSMutableDictionary dictionary];
	
	// Enumerate our columns and save width by column identifier
	NSEnumerator* colEnum = [[self tableColumns] objectEnumerator];
	NSTableColumn* thisCol;
	while (thisCol = [colEnum nextObject])
	{
		NSMutableDictionary* thisColDict = [NSMutableDictionary dictionary];
		NSString* thisColID = [thisCol identifier];
		
		// Save width
		NSNumber* thisWidth = [NSNumber numberWithFloat:[thisCol width]];
		[thisColDict setObject:thisWidth forKey:kAutosavedColumnWidthKey];
		
		// Save index
		NSNumber* thisIndex = [NSNumber numberWithInt:[self columnWithIdentifier:[thisCol identifier]]];
		[thisColDict setObject:thisIndex forKey:kAutosavedColumnIndexKey];

		// Add it all to the big dict
		[autoDict setObject:thisColDict forKey:thisColID];
	}
	
	return autoDict;
}

- (void) adjustLayoutForAutosavedDictionary:(NSDictionary*)theDict
{
	// To get the column ordering right we have to make sure we "move" columns 
	// to their respective indices from left to right, so that we never upset
	// the order of indices. So let's get an ordering of our keys by column index.
	NSArray* sortedColumnKeys = [theDict keysSortedByValueUsingSelector:@selector(compareByAutosavedIndex:)];
		
	// Set widths and index to saved values
	NSEnumerator* idEnum = [sortedColumnKeys objectEnumerator];
	NSString* thisIdentifier;
	while (thisIdentifier = [idEnum nextObject])
	{
		NSDictionary* thisColDict = [theDict objectForKey:thisIdentifier];

		// Ensure proper column location
		int currentIndex = [self columnWithIdentifier:thisIdentifier];
		int desiredIndex = [[thisColDict objectForKey:kAutosavedColumnIndexKey] intValue];
		[self moveColumn:currentIndex toColumn:desiredIndex];
		
		// And adjust the width
		NSTableColumn* thisCol = [self tableColumnWithIdentifier:thisIdentifier];
		if (thisCol != nil)
		{
			// Disable autosizing magic, because it interferes with our noble efforts
			// to set the width to a darned specific value.
			int saveMask = [thisCol safeResizingMask];		
			[thisCol setSafeResizingMask:0];
			[thisCol setWidth:[[thisColDict objectForKey:kAutosavedColumnWidthKey] floatValue]];
			[thisCol setSafeResizingMask:saveMask];
		}
	}
}

@end

@implementation NSTableColumn (RSTableViewAutosaving)

// We implement a 1-stop wrapper for setResizingMask and setResizable as appropriate 
// for the version of Mac OS X we are being run against.

- (int) safeResizingMask
{
	// 10.4 and later has "resizingMask". Earlier than that just pretend like the resizable BOOL is a mask
	if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_3)
	{
		return [self resizingMask];
	}
	else
	{
		return [self isResizable];
	}
}

- (void) setSafeResizingMask:(int) maskOrBOOL
{
	if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_3)	// NSAppKitVersionNumber10_2_3
	{
		[self setResizingMask:maskOrBOOL];
	}
	else
	{
		[self setResizable:maskOrBOOL];
	}	
}

@end

@implementation NSDictionary (RSTableViewAutosaving)

// Implementing a custom comparator on NSDictionary is the easiest way to take care
// or reordering by a sub-attribute (the autosaved column index).

- (NSComparisonResult)compareByAutosavedIndex:(NSDictionary *)otherDict
{	
	NSNumber* myIndex = [self objectForKey:kAutosavedColumnIndexKey];
	NSNumber* otherIndex = [otherDict objectForKey:kAutosavedColumnIndexKey];
	return [myIndex compare:otherIndex];
}

@end