/** NSApplication additions Copyright (c) 2000 Stefan Urbanek Written by: Stefan Urbanek Date: 2001 Nov 15 This file is part of the StepTalk project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "NSApplication+additions.h" #import "STScriptsPanel.h" #import "STTranscript.h" #import "STEnvironment+additions.h" #import #import #import #import #import #import #import #import #import #import #import "STApplicationScriptingController.h" static STEnvironment *scriptingEnvironment = nil; static NSMutableSet *scannedBundles; static STApplicationScriptingController *scriptingController = nil; @interface NSApplication (STPrivateMethods) - (void)updateScriptingInfoFromBundles; - (void)_createDefaultScriptingEnvironment; @end @implementation NSApplication(STAppScriptingAdditions) /** Method for preventing multiple initialization. It will show alert panel on invocation. You should not invoke this method.*/ - (BOOL)initializeApplicationScripting { /* FIXME: make it more human-readable */ NSRunAlertPanel(@"Scripting is already initialized", @"[NSApp initializeApplicationScripting] is called more than once.", @"Cancel", nil, nil); return YES; } /** Do real initialization of application scripting. You should not invoke this method directly. */ - (BOOL)setUpApplicationScripting { // STBundleInfo *info; // info = [STBundleInfo infoForBundle:[NSBundle mainBundle]]; /* FIXME: use info */ scriptingController = [[STApplicationScriptingController alloc] init]; return YES; } /** Return shared scripting environment. If there is none, create one. */ - (STEnvironment *)scriptingEnvironment { if(!scriptingEnvironment) { [self _createDefaultScriptingEnvironment]; } return scriptingEnvironment; } /** Create shared scripting environment. */ - (void)_createDefaultScriptingEnvironment { STEnvironmentDescription *desc; STEnvironment *env = nil; STBundleInfo *info; //NSString *path; NSString *str = nil; //NSString *reference; //NSDictionary *dict; //id object; NSDebugLog(@"Creating scripting environment"); scannedBundles = [[NSMutableSet alloc] init]; info = [STBundleInfo infoForBundle:[NSBundle mainBundle]]; if(!info) { NSRunAlertPanel(@"Application does not provide scripting capabilities", @"This application was designed to support " @"scripting, but something went wrong. " @"Check if the file ScriptingInfo.plist exists " @"in application's bundle directory.", @"Cancel", nil, nil); return; } [scannedBundles addObject:[NSBundle mainBundle]]; /* FIXME: use scripting environment from application bundle */ /* str = [info objectForKey:@"STEnvironmentDescription"]; */ if(str && ![str isEqualToString:@""]) { desc = [STEnvironmentDescription descriptionWithName:str]; env = [STEnvironment environmentWithDescription:desc]; } if(!env) { NSDebugLog(@"Using default scripting environment"); env = [STEnvironment environmentWithDefaultDescription]; } [env loadModule:@"AppKit"]; [env includeBundle:[NSBundle mainBundle]]; [env setObject:self forName:@"Application"]; [env setObject:self forName:[self applicationNameForScripting]]; [env setObject:[STTranscript sharedTranscript] forName:@"Transcript"]; scriptingEnvironment = RETAIN(env); [self updateScriptingInfoFromBundles]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateScriptingInfoOnBundleLoad:) name:NSBundleDidLoadNotification object:nil]; } /** Include information from loaded modules and bundles. */ - (void)updateScriptingInfoFromBundles { STEnvironment *env = [self scriptingEnvironment]; NSEnumerator *enumerator; //NSDictionary *info; //NSString *path; NSBundle *bundle; NSMutableSet *bundles; NSDebugLog(@"Updating scripting info from bundles"); bundles = (id)[NSMutableSet setWithArray:[NSBundle allBundles]]; [bundles minusSet:scannedBundles]; enumerator = [bundles objectEnumerator]; while( (bundle = [enumerator nextObject]) ) { /* If bundle provides scripting capabilities, try to include it. */ if([bundle scriptingInfoDictionary]) { if(![env includeBundle:bundle]) { NSLog(@"Failed to include bundle scripting of '%@'.", [bundle bundlePath]); } } } [scannedBundles unionSet:bundles]; } /** Called on NSBundleDidLoad notification. You */ - (void)updateScriptingInfoOnBundleLoad:(NSNotification *)notif { [self updateScriptingInfoFromBundles]; } /** Name of application object */ - (NSString *)applicationNameForScripting { return [[NSProcessInfo processInfo] processName]; } /** Order the scripts panel into the front. */ - (void)orderFrontScriptsPanel:(id)sender { [scriptingController orderFrontScriptsPanel:nil]; } /** Return scripting menu. The default menu is provided by STApplicationScriptingController */ - (NSMenu *)scriptingMenu { return [scriptingController scriptingMenu]; } /** Set application Scripting menu */ - (void)setScriptingMenu:(NSMenu *)menu { [scriptingController setScriptingMenu:menu]; } /** Order the Transcript window into the front. */ - (void)orderFrontTranscriptWindow:(id)sender { [scriptingController orderFrontTranscriptWindow:nil]; } /** Return YES if scripting is supported, otherwise returns NO. Because this method is called when framework is loaded, allways returns YES. */ - (BOOL)isScriptingSupported { return YES; } /** Return object that is responsible for controlling application scriptign */ - (STApplicationScriptingController *)scriptingController { return scriptingController; } @end