// // JSRun_AppDelegate.m // JSRun // // Created by Jonathan Saggau on 11/23/06. // Copyright Jonathan Saggau 2006 . All rights reserved. // #import "JSRun_AppDelegate.h" #import "JSMORun.h" #import "JSRunXmlParser.h" #import "JSRunGLVizController.h" #import "GLView.h" #import "JSCommonMacros.h" #import "JSMORunEvents.h" #import "JSMONode.h" #import "JSMOGraph.h" #import "JSMOGraphPrefs.h" @interface JSRun_AppDelegate (PrivateAPI) - (void)firstApplicationRun; @end @implementation JSRun_AppDelegate - (void)openGraphSettings; { [graphSettingsWindow makeKeyAndOrderFront:self]; } - (void)openXMLFile { NSArray *fileTypes = [NSArray arrayWithObject:@"xml"]; NSOpenPanel *oPanel = [NSOpenPanel openPanel]; NSString *startingDir = [[NSUserDefaults standardUserDefaults] objectForKey:@"StartingDirectory"]; if (!startingDir){ startingDir = NSHomeDirectory(); } [oPanel setAllowsMultipleSelection:YES]; [oPanel beginSheetForDirectory:startingDir file:nil types:fileTypes modalForWindow:window modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; } - (void)_selectLastRun { int selectionIndex = [[runsController arrangedObjects] count] - 1; [runsController setSelectionIndex: selectionIndex]; } - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { NSString *pathToFile; NSURL *xmlURL; if (returnCode == NSOKButton) { NSEnumerator *fileNamesEnum = [[sheet filenames] objectEnumerator]; //NSLog(@"FileNames = %@", [sheet filenames]); while (pathToFile = [fileNamesEnum nextObject]) { NSString *startingDir = [pathToFile stringByDeletingLastPathComponent]; [[NSUserDefaults standardUserDefaults] setObject:startingDir forKey:@"StartingDirectory"]; xmlURL = [NSURL fileURLWithPath:pathToFile]; //NSLog(@"xmlURL = %@", xmlURL); //the parser by default gets the moc from the app delegate (self) JSRunXmlParser *parser = [[JSRunXmlParser alloc] initWithContentsOfURL:xmlURL]; //NSLog(@"Parsing"); [parser parse]; [pathToFile release]; [parser release]; [self performSelector:@selector(_selectLastRun) withObject:nil afterDelay:(NSTimeInterval)0.0]; } } } - (IBAction)open:(id)sender; { [self openXMLFile]; } - (void)firstApplicationRun { //Inserting the App entity will automatically build (see various _sanitize... bits) //the necessary subobjects //JSMOApp *app = [NSEntityDescription insertNewObjectForEntityForName:@"App" inManagedObjectContext:[self managedObjectContext]]; [self saveAction:nil]; } - (void) _manualBindings { NSLog(@"Binding rundata to viz controller"); [vizController bind:@"runData" toObject:runsController withKeyPath:@"selection.self" options:nil]; NSLog(@"Binding Unit to UnitPrefs"); [vizController bind:@"unit" toObject:appController withKeyPath:@"selection.prefs.unitOfMeasure.unit" options:nil]; } - (void) _unbindManualBindings { [vizController unbind:@"runData"]; [vizController unbind:@"showSplits"]; } - (void) awakeFromNib { // this builds an empty graph if we're in first run [self persistentStoreCoordinator]; [self _manualBindings]; } #pragma mark - #pragma mark apple supplied methods; some modified slightly /** Returns the support folder for the application, used to store the Core Data store file. This code uses a folder named "JSRun" for the content, either in the NSApplicationSupportDirectory location or (if the former cannot be found), the system's temporary directory. */ - (NSString *)applicationSupportFolder { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory(); return [basePath stringByAppendingPathComponent:@"JSRun"]; } /** Creates, retains, and returns the managed object model for the application by merging all of the models found in the application bundle and all of the framework bundles. */ - (NSManagedObjectModel *)managedObjectModel { if (managedObjectModel != nil) { return managedObjectModel; } NSMutableSet *allBundles = [[NSMutableSet alloc] init]; [allBundles addObject: [NSBundle mainBundle]]; [allBundles addObjectsFromArray: [NSBundle allFrameworks]]; managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles: [allBundles allObjects]] retain]; [allBundles release]; return managedObjectModel; } /** Returns the persistent store coordinator for the application. This implementation will create and return a coordinator, having added the store for the application to it. (The folder for the store is created, if necessary.) */ - (NSPersistentStoreCoordinator *) persistentStoreCoordinator { if (persistentStoreCoordinator != nil) { return persistentStoreCoordinator; } NSFileManager *fileManager; NSString *applicationSupportFolder = nil; NSURL *url; NSError *error; fileManager = [NSFileManager defaultManager]; applicationSupportFolder = [self applicationSupportFolder]; if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) { NSLog(@"Creating app support directory and building a new Managed object graph"); [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil]; [self firstApplicationRun]; } url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"JSRun.xml"]]; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]){ [[NSApplication sharedApplication] presentError:error]; } return persistentStoreCoordinator; } /** Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) */ - (NSManagedObjectContext *) managedObjectContext { if (managedObjectContext != nil) { return managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { managedObjectContext = [[NSManagedObjectContext alloc] init]; [managedObjectContext setPersistentStoreCoordinator: coordinator]; } return managedObjectContext; } /** Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application. */ - (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window { return [[self managedObjectContext] undoManager]; } /** Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user. */ - (IBAction) saveAction:(id)sender { NSError *error = nil; if (![[self managedObjectContext] save:&error]) { NSLog(@"ERROR Description= %@", [error localizedDescription]); NSLog(@"ERROR Reason= %@", [error localizedFailureReason]); [[NSApplication sharedApplication] presentError:error]; } } /** Implementation of the applicationShouldTerminate: method, used here to handle the saving of changes in the application managed object context before the application terminates. */ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { NSError *error; int reply = NSTerminateNow; if (managedObjectContext != nil) { if ([managedObjectContext commitEditing]) { if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { if (error) { NSLog(@"Error = %@", error); NSLog(@"Error Description = %@", [error localizedDescription]); NSLog(@"Error Failure Reason = %@", [error localizedFailureReason]); NSLog(@"Error recovery options = %@", [error localizedRecoveryOptions]); NSLog(@"Error recovery suggestion = %@", [error localizedRecoverySuggestion]); } BOOL errorResult = [[NSApplication sharedApplication] presentError:error]; if (errorResult == YES) { reply = NSTerminateCancel; } else { int alertReturn = NSRunAlertPanel(nil, @"Could not save changes while quitting. Quit anyway?" , @"Quit anyway", @"Cancel", nil); if (alertReturn == NSAlertAlternateReturn) { reply = NSTerminateCancel; } } } } else { reply = NSTerminateCancel; } } return reply; } /** Implementation of dealloc, to release the retained variables. */ - (void) dealloc { [managedObjectContext release], managedObjectContext = nil; [persistentStoreCoordinator release], persistentStoreCoordinator = nil; [managedObjectModel release], managedObjectModel = nil; [self _unbindManualBindings]; [super dealloc]; } @end