ResKnife/Cocoa/Classes/OutlineViewDelegate.m

280 lines
12 KiB
Objective-C

#import "OutlineViewDelegate.h"
#import "Resource.h"
#import "ResourceDocument.h"
#import "ResourceDataSource.h"
#import "ResourceNameCell.h"
#import "ApplicationDelegate.h"
@implementation OutlineViewDelegate
- (id)init
{
self = [super init];
if(!self) return nil;
if(NSAppKitVersionNumber >= 700.0) // darwin 7.0 == Mac OS 10.3, needed for -setPlaceholderString:
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceNameDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceTypeDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceholder:) name:ResourceIDDidChangeNotification object:nil];
}
return self;
}
- (void)updatePlaceholder:(NSNotification *)notification
{
Resource *resource = [notification object];
ResourceNameCell *cell = (ResourceNameCell *) [[outlineView tableColumnWithIdentifier:@"name"] dataCellForRow:[outlineView rowForItem:resource]];
if([[resource name] isEqualToString:@""])
{
if([[resource resID] shortValue] == -16455)
[cell setPlaceholderString:NSLocalizedString(@"Custom Icon", nil)];
else [cell setPlaceholderString:NSLocalizedString(@"Untitled Resource", nil)];
}
}
/*!
@method tableView:didClickTableColumn:
@pending not needed in 10.3+, use existing sort functionality
*/
- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn
{
NSArray *newResources;
NSArray *oldResources = [(ResourceDataSource *)[tableView dataSource] resources];
// sort the array
NSImage *indicator = [tableView indicatorImageInTableColumn:tableColumn];
NSImage *upArrow = [NSTableView _defaultTableHeaderSortImage];
if(indicator == upArrow)
newResources = [oldResources sortedArrayUsingFunction:compareResourcesAscending context:[tableColumn identifier]];
else newResources = [oldResources sortedArrayUsingFunction:compareResourcesDescending context:[tableColumn identifier]];
// swap new array for old one
[(ResourceDataSource *)[tableView dataSource] setResources:[NSMutableArray arrayWithArray:newResources]];
[tableView reloadData];
}
/*!
@function compareResourcesAscending
@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare
*/
int compareResourcesAscending(Resource *r1, Resource *r2, void *context)
{
NSString *key = (NSString *)context;
// compare two NSStrings (case-insensitive)
if([key isEqualToString:@"name"] || [key isEqualToString:@"type"])
return [(NSString *)[r1 valueForKey:key] caseInsensitiveCompare:(NSString *)[r2 valueForKey:key]];
// compare two NSNumbers (or any other class)
else return [(NSNumber *)[r1 valueForKey:key] compare:(NSNumber *)[r2 valueForKey:key]];
}
/*!
@function compareResourcesDescending
@updated 2003-10-25 NGS: now uses KVC methods to obtain the strings to compare
*/
int compareResourcesDescending(Resource *r1, Resource *r2, void *context)
{
NSString *key = (NSString *)context;
// compare two NSStrings (case-insensitive)
if([key isEqualToString:@"name"] || [key isEqualToString:@"type"])
return -1 * [(NSString *)[r1 valueForKey:key] caseInsensitiveCompare: (NSString *)[r2 valueForKey:key]];
// compare two NSNumbers (or any other class)
else return -1 * [(NSNumber *)[r1 valueForKey:key] compare: (NSNumber *)[r2 valueForKey:key]];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
if([[tableColumn identifier] isEqualToString:@"size"] || [[tableColumn identifier] isEqualToString:@"attributes"])
return NO;
else return YES;
}
/*!
@method outlineView:willDisplayCell:forTableColumn:item:
@updated 2003-10-25 NGS: Moved functionality of NameFormatter into this method, removed NameFormatter class.
@updated 2003-10-24 NGS: Swapped row colours so first row is white (as per 10.3), conditionalised drawing line background colours to system versions < 10.3, since in 10.3 it is handled by the nib file.
@updated 2003-10-24 NGS: Added iconForResourceType method to app delegate instead of interrogating the cache here.
@pending remove setting of the cell formatter when that capability is in interface builder
*/
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
Resource *resource = (Resource *)item;
NSString *identifier = [tableColumn identifier];
// set formatters for cells (remove when IB can set a formatter for an entire table column)
if([identifier isEqualToString:@"size"]) [cell setFormatter:sizeFormatter];
else if([identifier isEqualToString:@"attributes"]) [cell setFormatter:attributesFormatter];
// set resource icon
if([identifier isEqualToString:@"name"])
{
if(![resource representedFork])
[(ResourceNameCell *)cell setImage:[(ApplicationDelegate *)[NSApp delegate] iconForResourceType:[resource type]]];
else [(ResourceNameCell *)cell setImage:[(ApplicationDelegate *)[NSApp delegate] iconForResourceType:nil]];
if([[resource name] isEqualToString:@""])
{
if([cell respondsToSelector:@selector(setPlaceholderString:)]) // 10.3+
{
// 10.3+ uses placeholder strings
if([[resource resID] shortValue] == -16455) // don't bother checking type since there are too many icon types
[cell setPlaceholderString:NSLocalizedString(@"Custom Icon", nil)];
else if([[resource type] isEqualToString:@"carb"] && [[resource resID] shortValue] == 0)
[cell setPlaceholderString:NSLocalizedString(@"Carbon Identifier", nil)];
else if([[resource type] isEqualToString:@"pnot"] && [[resource resID] shortValue] == 0)
[cell setPlaceholderString:NSLocalizedString(@"File Preview", nil)];
else if([[resource type] isEqualToString:@"STR "] && [[resource resID] shortValue] == -16396)
[cell setPlaceholderString:NSLocalizedString(@"Creator Information", nil)];
else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 1)
[cell setPlaceholderString:NSLocalizedString(@"File Version", nil)];
else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 2)
[cell setPlaceholderString:NSLocalizedString(@"Package Version", nil)];
else [cell setPlaceholderString:NSLocalizedString(@"Untitled Resource", nil)];
}
else
{
// pre-10.3, set text colour to grey and set title accordingly
if([[resource resID] shortValue] == -16455)
[cell setTitle:NSLocalizedString(@"Custom Icon", nil)];
else if([[resource type] isEqualToString:@"carb"] && [[resource resID] shortValue] == 0)
[cell setTitle:NSLocalizedString(@"Carbon Identifier", nil)];
else if([[resource type] isEqualToString:@"pnot"] && [[resource resID] shortValue] == 0)
[cell setTitle:NSLocalizedString(@"File Preview", nil)];
else if([[resource type] isEqualToString:@"STR "] && [[resource resID] shortValue] == -16396)
[cell setTitle:NSLocalizedString(@"Creator Information", nil)];
else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 1)
[cell setTitle:NSLocalizedString(@"File Version", nil)];
else if([[resource type] isEqualToString:@"vers"] && [[resource resID] shortValue] == 2)
[cell setTitle:NSLocalizedString(@"Package Version", nil)];
else [cell setTitle:NSLocalizedString(@"Untitled Resource", nil)];
// if([[outlineView selectedItems] containsObject:resource])
// [cell setTextColor:[NSColor whiteColor]];
// else [cell setTextColor:[NSColor grayColor]];
}
}
}
// draw alternating blue/white backgrounds (if pre-10.3)
if(NSAppKitVersionNumber < 700.0)
{
int row = [outlineView rowForItem:item];
if(row % 2) [cell setBackgroundColor:[NSColor colorWithCalibratedRed:0.93 green:0.95 blue:1.0 alpha:1.0]];
else [cell setBackgroundColor:[NSColor whiteColor]];
[cell setDrawsBackground:YES];
}
}
@end
@implementation RKOutlineView
/*!
@method draggingSourceOperationMaskForLocal:
*/
- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)local
{
if(local) return NSDragOperationEvery;
else return NSDragOperationCopy;
}
- (void)keyDown:(NSEvent *)event
{
int selectedRow = [self selectedRow];
if(selectedRow != -1 && [[event characters] isEqualToString:[NSString stringWithCString:"\r"]])
[self editColumn:0 row:selectedRow withEvent:nil select:YES];
else if(selectedRow != -1 && [[event characters] isEqualToString:[NSString stringWithCString:"\x7F"]])
[(ResourceDocument *)[[[self window] windowController] document] deleteSelectedResources];
else [super keyDown:event];
}
- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)selector
{
// pressed return, end editing
if(selector == @selector(insertNewline:))
{
[[self window] makeFirstResponder:self];
[self abortEditing];
return YES;
}
// pressed tab, move to next editable field
else if(selector == @selector(insertTab:))
{
int newColumn = ([self editedColumn] +1) % [self numberOfColumns];
NSString *newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier];
if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"])
{
newColumn = (newColumn +1) % [self numberOfColumns];
newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier];
if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"])
newColumn = (newColumn +1) % [self numberOfColumns];
}
[self editColumn:newColumn row:[self selectedRow] withEvent:nil select:YES];
return YES;
}
// pressed shift-tab, move to previous editable field
else if(selector == @selector(insertBacktab:))
{
int newColumn = ([self editedColumn] + [self numberOfColumns] -1) % [self numberOfColumns];
NSString *newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier];
if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"])
{
newColumn = (newColumn + [self numberOfColumns] -1) % [self numberOfColumns];
newColIdentifier = [[[self tableColumns] objectAtIndex:newColumn] identifier];
if([newColIdentifier isEqualToString:@"size"] || [newColIdentifier isEqualToString:@"attributes"])
newColumn = (newColumn + [self numberOfColumns] -1) % [self numberOfColumns];
}
[self editColumn:newColumn row:[self selectedRow] withEvent:nil select:YES];
return YES;
}
return NO;
}
/*!
@method _sendDelegateDidClickColumn:
@pending not needed in 10.3+, use existing sort functionality
*/
//- (void)_sendDelegateDidMouseDownInHeader:(int)columnIndex
- (void)_sendDelegateDidClickColumn:(int)columnIndex
{
// if(NSAppKitVersionNumber < 700.0)
{
NSTableColumn *tableColumn = [[self tableColumns] objectAtIndex:columnIndex];
NSImage *indicator = [self indicatorImageInTableColumn:tableColumn];
NSImage *upArrow = [NSTableView _defaultTableHeaderSortImage];
NSImage *downArrow = [NSTableView _defaultTableHeaderReverseSortImage];
if(indicator)
{
// column already selected
if(indicator == upArrow)
[self setIndicatorImage:downArrow inTableColumn:tableColumn];
else [self setIndicatorImage:upArrow inTableColumn:tableColumn];
}
else // new column selected
{
// if there is an existing selection, clear it's image
if([self highlightedTableColumn] != nil)
[self setIndicatorImage:nil inTableColumn:[self highlightedTableColumn]];
// sort name and type columns ascending by default
if([[tableColumn identifier] isEqualToString:@"name"] || [[tableColumn identifier] isEqualToString:@"type"])
[self setIndicatorImage:upArrow inTableColumn:tableColumn];
// sort all other columns descending by default
else [self setIndicatorImage:downArrow inTableColumn:tableColumn];
[self setHighlightedTableColumn:tableColumn];
}
[[self delegate] tableView:self didClickTableColumn:tableColumn];
}
// else [super _sendDelegateDidClickColumn:columnIndex];
}
@end