ResKnife/NovaTools/DataSource.m

152 lines
4.4 KiB
Objective-C
Executable File

#import "DataSource.h"
#import "ResKnifeResourceProtocol.h"
#import "NSNumber-Range.h"
@implementation DataSource
- (id)init
{
[self autorelease];
return nil;
}
- (id)initForType:(NSString *)typeString
{
self = [super init];
type = [typeString copy];
data = [[NSMutableDictionary alloc] init];
{
id <ResKnifeResourceProtocol> resource;
NSArray *resources = [NSClassFromString(@"Resource") allResourcesOfType:type inDocument:nil]; // nil document will search in ANY open document for the correct resource
NSEnumerator *enumerator = [resources objectEnumerator];
while( resource = [enumerator nextObject] )
[data setObject:[resource name] forKey:[resource resID]];
}
parsed = [[NSMutableArray alloc] initWithArray:[data allValues]];
return self;
}
- (void)dealloc
{
[type release];
[data release];
[parsed release];
[super dealloc];
}
- (NSDictionary *)data
{
return data;
}
- (void)setData:(NSMutableDictionary *)newData
{
id old = data;
data = [newData retain];
[self parseForString:@"" sorted:YES];
[old autorelease];
}
- (void)setString:(NSString *)string forResID:(int)resID
{
[data setObject:string forKey:[NSNumber numberWithInt:resID]];
}
- (void)parseForString:(NSString *)string sorted:(BOOL)sort
{
// bug: for some reason +[NSNumber isBoundedByRange:] doesn't like a range with a minimum below -30,000 (such as INT16_MIN), so I'm using INT8_MIN and screw everyone using resource IDs below that :P
[self parseForString:string withinRange:NSMakeRange(INT8_MIN, INT16_MAX) sorted:sort];
}
- (void)parseForString:(NSString *)string withinRange:(NSRange)resIDRange sorted:(BOOL)sort
{
NSNumber *resID;
NSString *trimmedString = [DataSource resNameFromStringValue:string];
NSEnumerator *enumerator = [[data allKeys] objectEnumerator];
[parsed removeAllObjects];
if( trimmedString == nil ) trimmedString = @"";
while( resID = [enumerator nextObject] )
{
NSString *value = [data objectForKey:resID];
NSRange range = [value rangeOfString:trimmedString options:NSCaseInsensitiveSearch];
if( ((range.location != NSNotFound && range.length != 0) || [trimmedString isEqualToString:@""]) && [resID isBoundedByRange:resIDRange] )
[parsed addObject:[self stringValueForResID:resID]];
}
// crap hack to allow user to change the insertion point if what they typed doesn't yet match an existing resource
if( [parsed count] == 0 ) [parsed addObject:string];
// sort case insensitive if sorting is requested
if( sort ) [parsed sortUsingSelector:@selector(caseInsensitiveCompare:)];
}
- (id)objectValueForResID:(NSNumber *)resID
{
return [data objectForKey:resID];
}
- (NSString *)stringValueForResID:(NSNumber *)resID
{
if( resID && [data objectForKey:resID] )
return [NSString stringWithFormat:@"%@ {%@}", [data objectForKey:resID], resID];
else if( [resID shortValue] == -1 )
return @"";
else if( resID )
return [NSString stringWithFormat:@"{%@}", resID];
return nil;
}
+ (NSNumber *)resIDFromStringValue:(NSString *)string
{
NSRange span, range = NSMakeRange(0,0);
span = [string rangeOfString:@"{" options:NSBackwardsSearch];
if( span.location != NSNotFound ) range.location = span.location +1;
else return [NSNumber numberWithInt:-1];
span = [string rangeOfString:@"}" options:NSBackwardsSearch];
if( span.location != NSNotFound ) range.length = span.location - range.location;
else return [NSNumber numberWithInt:-1];
NS_DURING
NS_VALUERETURN( [[[NSNumber alloc] initWithInt:[[string substringWithRange:range] intValue]] autorelease], NSNumber* );
NS_HANDLER
NS_VALUERETURN( [NSNumber numberWithInt:-1], NSNumber* );
NS_ENDHANDLER
}
+ (NSString *)resNameFromStringValue:(NSString *)string
{
NSRange range = [string rangeOfString:@"{" options:NSBackwardsSearch];
if( range.location != NSNotFound && range.location > 0 )
return [string substringToIndex:range.location -1];
else if( range.location == 0 )
return nil;
else return string;
}
/* NSComboBox Informal Prototype Implementation */
- (id)comboBox:(NSComboBox *)comboBox objectValueForItemAtIndex:(int)index
{
return [parsed objectAtIndex:index];
}
- (int)numberOfItemsInComboBox:(NSComboBox *)comboBox
{
return [parsed count];
}
/* Combo Box Delegate Methods */
- (BOOL)control:(NSControl *)control isValidObject:(id)object
{
return [parsed containsObject:object];
}
/* Description */
- (NSString *)description
{
return [NSString stringWithFormat:@"\nType: %@\nData: %@\nParsed Data: %@\n", type, [data description], [parsed description]];
}
@end