/* GormPluginManager.m * * Copyright (C) 1999 Free Software Foundation, Inc. * * Author: Richard Frith-Macdonald * Author: Gregory John Casamento * Date: 1999, 2004, 2008 * * This file is part of GNUstep. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #include "GormPrivate.h" #include #include #include #include #include #include "GormFunctions.h" #include "GormPluginManager.h" #define BUILTIN_PLUGINS @"BuiltinPlugins" #define USER_PLUGINS @"UserPlugins" @implementation GormPluginManager - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; RELEASE(bundles); RELEASE(plugins); RELEASE(pluginsDict); [super dealloc]; } /* - (void) handleNotification: (NSNotification*)aNotification { NSString *name = [aNotification name]; if ([name isEqual: IBWillBeginTestingInterfaceNotification] == YES) { if ([panel isVisible] == YES) { hiddenDuringTest = YES; [panel orderOut: self]; } } else if ([name isEqual: IBWillEndTestingInterfaceNotification] == YES) { if (hiddenDuringTest == YES) { hiddenDuringTest = NO; [panel orderFront: self]; } } } */ - (id) init { NSArray *array; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSArray *userPlugins = [defaults arrayForKey: USER_PLUGINS]; // NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; self = [super init]; if(self != nil) { /* if([NSBundle loadNibNamed: @"GormPluginPanel" owner: self] == NO) { return nil; } */ } else { return nil; } // // Initialize dictionary // pluginsDict = [[NSMutableDictionary alloc] init]; plugins = [[NSMutableArray alloc] init]; pluginNames = [[NSMutableArray alloc] init]; // // Set frame name // // [panel setFrameUsingName: @"Plugins"]; // [panel setFrameAutosaveName: @"Plugins"]; array = [[NSBundle mainBundle] pathsForResourcesOfType: @"plugin" inDirectory: nil]; if ([array count] > 0) { unsigned index; array = [array sortedArrayUsingSelector: @selector(compare:)]; for (index = 0; index < [array count]; index++) { [self loadPlugin: [array objectAtIndex: index]]; } } // if we have any user plugins load them as well. if(userPlugins != nil) { NSEnumerator *en = [userPlugins objectEnumerator]; id pluginName = nil; while((pluginName = [en nextObject]) != nil) { [self loadPlugin: pluginName]; } } /* [nc addObserver: self selector: @selector(handleNotification:) name: IBWillBeginTestingInterfaceNotification object: nil]; [nc addObserver: self selector: @selector(handleNotification:) name: IBWillEndTestingInterfaceNotification object: nil]; */ return self; } - (BOOL) bundlePathIsLoaded: (NSString *)path { int col = 0; NSBundle *bundle; for (col = 0; col < [bundles count]; col++) { bundle = [bundles objectAtIndex: col]; if ([path isEqualToString: [bundle bundlePath]] == YES) { return YES; } } return NO; } - (BOOL) loadPlugin: (NSString*)path { NSBundle *bundle; NSString *className; IBPlugin *plugin; Class pluginClass; //NSDictionary *pluginInfo; //NSWindow *window; //NSArray *exportClasses; //NSArray *exportSounds; //NSArray *exportImages; //NSDictionary *subClasses; if([self bundlePathIsLoaded: path]) { NSRunAlertPanel (nil, _(@"Plugin has already been loaded"), _(@"OK"), nil, nil); return NO; } bundle = [NSBundle bundleWithPath: path]; if (bundle == nil) { NSRunAlertPanel(nil, _(@"Could not load Plugin"), _(@"OK"), nil, nil); return NO; } /* May use this later for class description path = [bundle pathForResource: @"plugin" ofType: @"table"]; if (path == nil) { NSRunAlertPanel(nil, _(@"File 'palette.table' missing"), _(@"OK"), nil, nil); return NO; } // attempt to load the palette table in either the strings or plist format. NS_DURING { paletteInfo = [[NSString stringWithContentsOfFile: path] propertyList]; if (paletteInfo == nil) { paletteInfo = [[NSString stringWithContentsOfFile: path] propertyListFromStringsFileFormat]; if(paletteInfo == nil) { NSRunAlertPanel(_(@"Problem Loading Palette"), _(@"Failed to load 'palette.table' using strings or property list format."), _(@"OK"), nil, nil); return NO; } } } NS_HANDLER { NSString *message = [NSString stringWithFormat: _(@"Encountered exception %@ attempting to load 'palette.table'."), [localException reason]]; NSRunAlertPanel(_(@"Problem Loading Palette"), message, _(@"OK"), nil, nil); return NO; } NS_ENDHANDLER */ className = [[bundle infoDictionary] objectForKey: @"NSPrincipalClass"]; if (className == nil) { NSRunAlertPanel(nil, _(@"No plugin class in plist"), _(@"OK"), nil, nil); return NO; } pluginClass = [bundle classNamed: className]; if (pluginClass == 0) { NSRunAlertPanel (nil, _(@"Could not load plugin class"), _(@"OK"), nil, nil); return NO; } plugin = [[pluginClass alloc] init]; if ([plugin isKindOfClass: [IBPlugin class]] == NO) { NSRunAlertPanel (nil, _(@"Plugin contains wrong type of class"), _(@"OK"), nil, nil); RELEASE(plugin); return NO; } // add to the bundles list... [bundles addObject: bundle]; /* exportClasses = [paletteInfo objectForKey: @"ExportClasses"]; if(exportClasses != nil) { [self importClasses: exportClasses withDictionary: nil]; } exportImages = [paletteInfo objectForKey: @"ExportImages"]; if(exportImages != nil) { [self importImages: exportImages withBundle: bundle]; } exportSounds = [paletteInfo objectForKey: @"ExportSounds"]; if(exportSounds != nil) { [self importSounds: exportSounds withBundle: bundle]; } subClasses = [paletteInfo objectForKey: @"SubstituteClasses"]; if(subClasses != nil) { [substituteClasses addEntriesFromDictionary: subClasses]; } */ [plugin didLoad]; // manage plugin data. [pluginsDict setObject: plugin forKey: className]; [plugins addObject: plugin]; [pluginNames addObject: className]; RELEASE(plugin); return YES; } - (id) openPlugin: (id) sender { NSArray *fileTypes = [NSArray arrayWithObject: @"plugin"]; NSOpenPanel *oPanel = [NSOpenPanel openPanel]; int result; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSArray *userPlugins = [defaults arrayForKey: USER_PLUGINS]; NSMutableArray *newUserPlugins = (userPlugins == nil)?[NSMutableArray array]:[NSMutableArray arrayWithArray: userPlugins]; [oPanel setAllowsMultipleSelection: YES]; [oPanel setCanChooseFiles: YES]; [oPanel setCanChooseDirectories: NO]; result = [oPanel runModalForDirectory: NSHomeDirectory() file: nil types: fileTypes]; if (result == NSOKButton) { NSArray *filesToOpen = [oPanel filenames]; unsigned count = [filesToOpen count]; unsigned i; for (i = 0; i < count; i++) { NSString *aFile = [filesToOpen objectAtIndex: i]; if([self bundlePathIsLoaded: aFile] == YES && [userPlugins containsObject: aFile] == NO) { [newUserPlugins addObject: aFile]; } else if([self loadPlugin: aFile] == NO) { return nil; } else { [newUserPlugins addObject: aFile]; } } // reset the defaults to include the new plugin. [defaults setObject: newUserPlugins forKey: USER_PLUGINS]; return self; } return nil; } /* - (NSPanel*) panel { return panel; } */ @end