/* Controller.m Implementation of the ArgumentsInspector class for the ProjectManager application. Copyright (C) 2005 Saso Kiselkov 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 2 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ #import "Controller.h" #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import "Preferences.h" #import "ProjectCreator.h" #import "ProjectDocument.h" #import "ProjectModule.h" #import "ProjectType.h" #import "ProjectTypeLoader.h" #import "ProjectWindowController.h" #import "TextFinder.h" #import "NewFileTypeChooser.h" /** * Posted when the user chooses a different document to be the * current document in the app. The user info dictionary can * either: * * - contain a single key named "Document" which contains the * document the user currenty chose. * * - or be `nil' in case no document is currently active. */ NSString * const CurrentDocumentDidChangeNotification = @"CurrentDocumentDidChangeNotification"; @interface Controller (Private) - (void) syncPipesMenu; - (void) registerProjectMenuEntries: (NSArray *) entries; - (void) deregisterProjectMenuEntries: (NSArray *) entries; @end @implementation Controller - (void) dealloc { NSDebugLLog(@"Controller", @"Controller: dealloc"); [[NSNotificationCenter defaultCenter] removeObserver: self]; DESTROY(projectMenuEntries); [super dealloc]; } - (void) awakeFromNib { pipesMenu = [pipesMenu submenu]; projectMenu = [projectMenu submenu]; [projectMenu removeItemAtIndex: 0]; [projectMenu sizeToFit]; } - (void) showPrefsPanel: (id)sender { [[Preferences shared] activate]; } - (void) newProject: sender { id document; NSString * projectPath; NSString * projectName; NSString * templatePath; NSDictionary * projectInfo; NSError * error; projectInfo = [[ProjectCreator shared] getNewProjectSetupWithLocation: YES]; if (projectInfo == nil) { return; } NSDebugLLog(@"Controller", _(@"New project info:\n%@"), projectInfo); projectPath = [projectInfo objectForKey: @"ProjectPath"]; projectName = [projectInfo objectForKey: @"ProjectName"]; templatePath = [projectInfo objectForKey: @"ProjectTemplate"]; if ([ProjectCreator createNewProjectAtPath: projectPath projectName: projectName fromTemplate: templatePath error: &error] == NO) { NSRunAlertPanel(_(@"Failed to create project"), _(@"I couldn't create a new project at the specified path.\n%@"), nil, nil, nil, [[error userInfo] objectForKey: NSLocalizedDescriptionKey]); return; } document = [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfFile: [projectPath stringByAppendingPathComponent: [[projectInfo objectForKey: @"ProjectName"] stringByAppendingPathExtension: @"pmproj"]] display: YES]; if (document != nil) { [document saveDocument: nil]; } } - (void) newSourceFile: sender { NewFileTypeChooser * chooser = [NewFileTypeChooser shared]; NSString * type; type = [chooser runModalWithRequiredKey: @"NSDocumentClass" value: @"SourceEditorDocument"]; if (type != nil) { [[NSDocumentController sharedDocumentController] openUntitledDocumentOfType: type display: YES]; } } - (void) applicationDidFinishLaunching: (NSNotification *) notif { NSNotificationCenter * nc = [NSNotificationCenter defaultCenter]; [self syncPipesMenu]; [nc addObserver: self selector: @selector(syncPipesMenu) name: NSUserDefaultsDidChangeNotification object: [NSUserDefaults standardUserDefaults]]; /* Watches for main window changes and posts CurrentProjectModuleDidChangeNotification's as appropriate, so that inspectors can gracefully follow main window changes */ NSDebugLLog(@"Controller", @"Controller: registering for main window changes"); [nc addObserver: self selector: @selector(mainWindowChanged:) name: NSWindowDidBecomeMainNotification object: nil]; } - (void) orderFrontFindPanel: sender { [[TextFinder sharedInstance] orderFrontFindPanel: self]; } - (void) mainWindowChanged: (NSNotification *) notif { id document; id wc; NSNotificationCenter * nc = [NSNotificationCenter defaultCenter]; wc = [[notif object] windowController]; if ([wc respondsToSelector: @selector(currentModule)]) { [nc postNotificationName: CurrentProjectModuleDidChangeNotification object: self userInfo: [NSDictionary dictionaryWithObject: [wc currentModule] forKey: @"Module"]]; } else { [nc postNotificationName: CurrentProjectModuleDidChangeNotification object: self userInfo: nil]; } // deregister old project menu entries if (projectMenuEntries != nil) { [self deregisterProjectMenuEntries: projectMenuEntries]; DESTROY(projectMenuEntries); } document = [wc document]; if (document != nil) { [nc postNotificationName: CurrentDocumentDidChangeNotification object: self userInfo: [NSDictionary dictionaryWithObject: document forKey: @"Document"]]; // and see if this document provides project menu entries document = [wc document]; if ([document respondsToSelector: @selector(projectMenuEntries)]) { ASSIGN(projectMenuEntries, [document projectMenuEntries]); [self registerProjectMenuEntries: projectMenuEntries]; } } else { [nc postNotificationName: CurrentDocumentDidChangeNotification object: self userInfo: nil]; } } @end @implementation Controller (Private) - (void) syncPipesMenu { unsigned int i, n; NSDictionary * userPipes; NSArray * allItems; NSEnumerator * e; NSString * itemTitle; for (i = 0, n = [pipesMenu numberOfItems]; i item = [pipesMenu itemAtIndex: i]; if (sel_eq([item action], @selector(pipeOutput:))) { [pipesMenu removeItemAtIndex: i]; i--; n--; } } userPipes = [[NSUserDefaults standardUserDefaults] objectForKey: @"UserPipes"]; allItems = [[userPipes allKeys] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; e = [allItems objectEnumerator]; while ((itemTitle = [e nextObject]) != nil) { [pipesMenu insertItemWithTitle: itemTitle action: @selector(pipeOutput:) keyEquivalent: [[userPipes objectForKey: itemTitle] objectForKey: @"KeyEquivalent"] atIndex: [allItems indexOfObject: itemTitle] + 1]; } } - (void) registerProjectMenuEntries: (NSArray *) entries { NSEnumerator * e; id item; NSDebugLLog(@"Controller", @"Controller: registering project menu " @"entries %@.", entries); e = [entries objectEnumerator]; while ((item = [e nextObject]) != nil) { [projectMenu addItem: item]; } } - (void) deregisterProjectMenuEntries: (NSArray *) entries { NSEnumerator * e; id item; NSDebugLLog(@"Controller", @"Controller: deregistering project menu " @"entries %@.", entries); e = [entries objectEnumerator]; while ((item = [e nextObject]) != nil) { [projectMenu removeItem: item]; } } @end