// // MPT_PluginBase.m // // Created by Andrew Salamon on 9/25/06. // Copyright (c) 2006 Machine Perception Laboratory, // University of California San Diego. All rights reserved. // #import "MPT_PluginBase.h" #import "MPT_AUView.h" @interface MPT_PluginBase(PrivateMethods) - (void)setBundle:(NSBundle *)_bundle; - (void)setLabels:(NSArray *)_labels; @end @implementation MPT_PluginBase + (int)stepOrderForStep:(NSString *)_step { if( [_step isEqualToString:MPT_PluginStep_Features] ) { return 1; } else if( [_step isEqualToString:MPT_PluginStep_SVM] ) { return 2; } else if( [_step isEqualToString:MPT_PluginStep_AfterFaces] ) { return 3; } else if( [_step isEqualToString:MPT_PluginStep_Frequencies] ) { return 4; } else if( [_step isEqualToString:MPT_PluginStep_Results] ) { return 5; } else if( [_step isEqualToString:MPT_PluginStep_NoStep] ) { return 0; } // default to MPT_PluginStep_NoStep but provide a warning NSLog( @"Unknown plugin step (%@) in [MPT_PluginBase stepOrderForStep:]", _step ); return 0; } - (id)initWithBundle:(NSBundle *)_bundle; { if( self = [super init] ) { isThreadCopy = NO; dependents = [[NSMutableArray alloc] init]; [self setBundle:_bundle]; [self loadLabels]; [self loadTooltips]; NSNumber *displaySetting = [[self bundle] objectForInfoDictionaryKey:@"Display"]; if( displaySetting && ([displaySetting boolValue] == NO) ) [self setDisplay:NO]; else [self setDisplay:YES]; views = [[NSMutableDictionary alloc] init]; [self initViews]; } return self; } - (id)init { return [self initWithBundle:nil]; } - (void)makeThreadsafe { // we don't want multiple copies of a plugin all trying to release these when they dealloc. dependents = nil; views = nil; labels = nil; tooltips = nil; delegate = nil; // We also don't want copies trying to call back to the delegate. isThreadCopy = YES; } - (id)copyWithZone:(NSZone *)zone { id cp = NSCopyObject( self, 0, zone ); [cp makeThreadsafe]; [cp setLabels:[[labels copy] autorelease]]; return cp; } - (void)initViews { NSEnumerator *labelEnum = [labels objectEnumerator]; NSString *label; while( label = [labelEnum nextObject] ) { MPT_AUView *view = [self viewForLabel:label]; if( !view ) { view = [[MPT_AUView alloc] init]; [view setAUString:label]; [self setView:view forLabel:label]; [view release]; } } } - (void)dealloc { [dependents release]; [views release]; [labels release]; [tooltips release]; [super dealloc]; } - (void)setLabels:(NSArray *)_labels { if( _labels != labels ) { [labels release]; labels = [_labels retain]; } } - (BOOL)loadLabels { NSString *labelFile = [[self bundle] pathForResource:@"labels" ofType:@"plist"]; if( [labelFile length] > 0 ) labels = [[NSArray alloc] initWithContentsOfFile:labelFile]; else labels = [[NSArray alloc] init]; return ([labels count] > 0); } - (void)setDelegate:(id)_delegate { delegate = _delegate; } - (id)delegate { return delegate; } - (NSString *)pluginID { NSString *ident = [[self bundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; if( [ident length] > 0 ) return ident; return nil; } - (NSString *)localizedName { NSAssert( YES, @"Improper use of base class. Subclasses must define localizedName method." ); return NSLocalizedStringFromTableInBundle(@"Unknown Name", nil, [self bundle], @""); } - (NSString *)internalName { NSAssert( YES, @"Improper use of base class. Subclasses must define internalName method." ); return @"MPT_PluginBase"; } - (NSString *)version { return [[self bundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; } - (NSArray *)labels { return labels; } - (MPT_AUView *)viewForLabel:(NSString *)label { if( ![self display] ) return nil; return [views objectForKey:label]; } - (void)setView:(MPT_AUView *)newView forLabel:(NSString *)label { MPT_AUView *view = [self viewForLabel:label]; if( newView != view ) { [views setObject:newView forKey:label]; [newView setEnabled:[self enabled]]; if( tooltips ) { NSString *tip = [tooltips objectForKey:label]; if( tip ) [newView setToolTip:tip]; } } } - (void)loadTooltips { NSString *tooltipFile = [[self bundle] pathForResource:@"tooltips" ofType:@"plist"]; if( [tooltipFile length] > 0 ) { NSArray *tooltipArray = [NSArray arrayWithContentsOfFile:tooltipFile]; if( ([tooltipArray count] > 0) && ([tooltipArray count] == [labels count]) ) { [tooltips release]; tooltips = [[NSDictionary alloc] initWithObjects:tooltipArray forKeys:labels]; } } } - (NSView *)prefPane { return nil; } - (NSString *)step { return MPT_PluginStep_NoStep; } - (int)stepOrder { return [MPT_PluginBase stepOrderForStep:[self step]]; } - (BOOL)enabled { return enabled; } - (void)setEnabled:(BOOL)value { if( enabled != value ) { enabled = value; if( [self delegate] && [[self delegate] respondsToSelector:@selector(didChangeEnabledStateForPlugin:)] ) [[self delegate] didChangeEnabledStateForPlugin:self]; } } - (BOOL)display { return display; } - (void)setDisplay:(BOOL)value { if( display != value ) { display = value; NSEnumerator *viewEnum = [views objectEnumerator]; MPT_AUView *view; while( view = [viewEnum nextObject] ) { [view setEnabled:display]; } if( !isThreadCopy ) { if( display ) { [self setEnabled:YES]; } else { if( [self hasDependents] ) { BOOL mustEnable = NO; NSEnumerator *depEnum = [dependents objectEnumerator]; id dep; while( !mustEnable && (dep = [depEnum nextObject]) ) { if( [dep enabled] ) mustEnable = YES; } if( mustEnable ) [self setEnabled:YES]; // this shouldn't be necessary, but just in case, make sure we are enabled if we have dependent plugins else [self setEnabled:NO]; } else { [self setEnabled:NO]; } } } if( [self delegate] && [[self delegate] respondsToSelector:@selector(didChangeEnabledStateForPlugin:)] ) [[self delegate] didChangeEnabledStateForPlugin:self]; } } - (void)setBundle:(NSBundle *)_bundle { if( _bundle != bundle ) { [bundle release]; bundle = [_bundle retain]; } } - (NSBundle *)bundle { return bundle; } - (id)getPrefForKey:(NSString *)key { NSDictionary *myPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]]; id pref = [myPrefs objectForKey:key]; return pref; } - (void)setPrefForKey:(NSString *)key to:(id)value { NSMutableDictionary *myPrefs = [[[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]] mutableCopy]; if( !myPrefs ) { myPrefs = [[NSMutableDictionary alloc] init]; [myPrefs setObject:[NSNumber numberWithBool:[self enabled]] forKey:@"enabled"]; } [myPrefs setObject:(value?value:@"") forKey:key]; [[NSUserDefaults standardUserDefaults] setObject:myPrefs forKey:[self pluginID]]; [myPrefs release]; } - (NSString *)desc { NSString *desc = NSLocalizedStringFromTableInBundle(@"description", nil, [self bundle], @""); if( !desc || [desc isEqualTo:@"description"] ) desc = @""; return desc; } - (int)sortOrder { return 10; } - (NSComparisonResult)pluginCompare:(id)otherPlugin { if( [otherPlugin sortOrder] > [self sortOrder] ) return NSOrderedAscending; if( [otherPlugin sortOrder] < [self sortOrder] ) return NSOrderedDescending; // if( [otherPlugin sortOrder] == [self sortOrder] ) // return NSOrderedSame; return NSOrderedSame; } - (NSArray *)dependencies { return nil; } - (void)addDependent:(id)dep { [dependents addObject:dep]; } - (BOOL)hasDependents { return ([dependents count] > 0); } @end