diff options
author | rowanbeentje <rowan@beent.je> | 2010-05-23 21:44:59 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2010-05-23 21:44:59 +0000 |
commit | c661b409eaa0e29d9e012b79e7a66574a554817a (patch) | |
tree | 49b310ded9a226a66aa53444c9ba112824854f68 /Source/SPAppController.m | |
parent | b66006f3755c6a57dfc60d4133bc4dc4da0fef56 (diff) | |
download | sequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.tar.gz sequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.tar.bz2 sequelpro-c661b409eaa0e29d9e012b79e7a66574a554817a.zip |
Initial implementation of tabs:
- Addition of PSMTabBar framework
- Rework away from a document-based TableDocument
- Support tabs throughout the application
- Add menu items for creating tabs, and add support for dragging tabs to different windows
Diffstat (limited to 'Source/SPAppController.m')
-rw-r--r-- | Source/SPAppController.m | 244 |
1 files changed, 165 insertions, 79 deletions
diff --git a/Source/SPAppController.m b/Source/SPAppController.m index b80e0680..5adacb8b 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -31,13 +31,14 @@ #import "TableDump.h" #import "SPEncodingPopupAccessory.h" #import "SPConstants.h" +#import "SPWindowController.h" #import <Sparkle/Sparkle.h> @implementation SPAppController /** - * Inialise the application's main controller, setting itself as the app delegate. + * Initialise the application's main controller, setting itself as the app delegate. */ - (id)init { @@ -96,14 +97,6 @@ */ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { - if ([menuItem action] == @selector(openConnectionSheet:) && [menuItem tag] == 0) - { - // Do not allow to open a sql/spf file if SP asks for connection details - if ([[[NSDocumentController sharedDocumentController] documents] count]) { - if(![[[[NSDocumentController sharedDocumentController] currentDocument] mySQLVersion] length]) - return NO; - } - } if ([menuItem action] == @selector(openCurrentConnectionInNewWindow:)) { [menuItem setTitle:NSLocalizedString(@"Open in New Window", @"menu item open in new window")]; @@ -160,13 +153,13 @@ // it will enabled if user selects a *.sql file [encodingPopUp setEnabled:NO]; - + // Check if at least one document exists, if so show a sheet - if ([[[NSDocumentController sharedDocumentController] documents] count]) { + if ([self frontDocumentWindow]) { [panel beginSheetForDirectory:nil file:@"" types:[NSArray arrayWithObjects:@"spf", @"sql", nil] - modalForWindow:[[[NSDocumentController sharedDocumentController] currentDocument] valueForKey:@"tableWindow"] + modalForWindow:[self frontDocumentWindow] modalDelegate:self didEndSelector:@selector(openConnectionPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; @@ -220,7 +213,7 @@ [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"cancel button")]; // Show 'Import' button only if there's a connection available - if ([[[NSDocumentController sharedDocumentController] documents] count]) + if ([self frontDocument]) [alert addButtonWithTitle:NSLocalizedString(@"Import", @"import button")]; @@ -237,49 +230,44 @@ if(returnCode == NSAlertSecondButtonReturn) return; // Cancel else if(returnCode == NSAlertThirdButtonReturn) { // Import // begin import process - [[[[NSDocumentController sharedDocumentController] currentDocument] valueForKeyPath:@"tableDumpInstance"] startSQLImportProcessWithFile:filename]; + [[[self frontDocument] valueForKeyPath:@"tableDumpInstance"] startSQLImportProcessWithFile:filename]; return; } } } } + // Attempt to open the file into a string. + NSString *sqlString = nil; + + // If the user came from an openPanel use the chosen encoding + if (encodingPopUp) { + NSError *error = nil; + sqlString = [NSString stringWithContentsOfFile:filename encoding:[[encodingPopUp selectedItem] tag] error:&error]; + if(error != nil) { + NSAlert *errorAlert = [NSAlert alertWithError:error]; + [errorAlert runModal]; + return; + } + + // Otherwise, read while attempting to autodetect the encoding + } else { + sqlString = [self contentOfFile:filename]; + } + // if encodingPopUp is defined the filename comes from an openPanel and // the encodingPopUp contains the chosen encoding; otherwise autodetect encoding if(encodingPopUp) [[NSUserDefaults standardUserDefaults] setInteger:[[encodingPopUp selectedItem] tag] forKey:SPLastSQLFileEncoding]; - // Check if at least one document exists - if (![[[NSDocumentController sharedDocumentController] documents] count]) { - - TableDocument *firstTableDocument; - - // Manually open a new document, setting SPAppController as sender to trigger autoconnection - if (firstTableDocument = [[NSDocumentController sharedDocumentController] makeUntitledDocumentOfType:@"Sequel Pro connection" error:nil]) { - [firstTableDocument setShouldAutomaticallyConnect:NO]; - - // user comes from a openPanel? if so use the chosen encoding - if(encodingPopUp) { - NSError *error = nil; - NSString *content = [NSString stringWithContentsOfFile:filename encoding:[[encodingPopUp selectedItem] tag] error:&error]; - if(error != nil) { - NSAlert *errorAlert = [NSAlert alertWithError:error]; - [errorAlert runModal]; - return; - } - [firstTableDocument initQueryEditorWithString:content]; - - } - else - [firstTableDocument initQueryEditorWithString:[self contentOfFile:filename]]; - - [[NSDocumentController sharedDocumentController] addDocument:firstTableDocument]; - [firstTableDocument makeWindowControllers]; - [firstTableDocument showWindows]; - } + // Check if at least one document exists. If not, open one. + if (![self frontDocument]) { + [self newWindow:self]; + [[self frontDocument] initQueryEditorWithString:sqlString]; } else { + // Pass query to the Query editor of the current document - [[[NSDocumentController sharedDocumentController] currentDocument] doPerformLoadQueryService:[self contentOfFile:filename]]; + [[self frontDocument] doPerformLoadQueryService:[self contentOfFile:filename]]; } break; // open only the first SQL file @@ -289,15 +277,12 @@ TableDocument *newTableDocument; - // Manually open a new document, setting SPAppController as sender to trigger autoconnection - if (newTableDocument = [[NSDocumentController sharedDocumentController] makeUntitledDocumentOfType:@"Sequel Pro connection" error:nil]) { - [newTableDocument setShouldAutomaticallyConnect:NO]; - [[NSDocumentController sharedDocumentController] addDocument:newTableDocument]; - [newTableDocument makeWindowControllers]; - [newTableDocument showWindows]; - [newTableDocument initWithConnectionFile:filename]; + // If the frontmost document isn't connected and hasn't been, open the connection file with it. + // Otherwise, manually open a new document, setting SPAppController as sender to trigger autoconnection + if ([[self frontDocument] mySQLVersion]) { + [self newWindow:self]; } - + [[self frontDocument] initWithConnectionFile:filename]; } else { NSLog(@"Only files with the extensions ‘spf’ or ‘sql’ are allowed."); @@ -306,6 +291,81 @@ } #pragma mark - +#pragma mark Window management + +/** + * Create a new window, containing a single tab. + */ +- (IBAction)newWindow:(id)sender +{ + static NSPoint cascadeLocation = {.x = 0, .y = 0}; + + // Create a new window controller, and set up a new connection view within it. + SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; + NSWindow *newWindow = [newWindowController window]; + [newWindow setReleasedWhenClosed:YES]; + + // Cascading defaults to on - retrieve the window origin automatically assigned by cascading, + // and convert to a top left point. + NSPoint topLeftPoint = [newWindow frame].origin; + topLeftPoint.y += [newWindow frame].size.height; + + // The first window should use autosaving; subsequent windows should cascade. + // So attempt to set the frame autosave name; this will succeed for the very + // first window, and fail for others. + BOOL usedAutosave = [newWindow setFrameAutosaveName:@"DBView"]; + if (!usedAutosave) { + [newWindow setFrameUsingName:@"DBView"]; + } + + // Cascade according to the statically stored cascade location. + cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; + + // Set the window controller as the window's delegate + [newWindow setDelegate:newWindowController]; + + // Show the window + [newWindowController showWindow:self]; +} + +/** + * Create a new tab in the frontmost window. + */ +- (IBAction)newTab:(id)sender +{ + SPWindowController *frontController = nil; + + for (NSWindow *aWindow in [self orderedWindows]) { + if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { + frontController = [aWindow windowController]; + break; + } + } + + // If no window was found, create a new one + if (!frontController) { + [self newWindow:self]; + } else { + if ([[frontController window] isMiniaturized]) [[frontController window] deminiaturize:self]; + [frontController addNewConnection:self]; + } +} + +/** + * Retrieve the frontmost document window; returns nil if not found. + */ +- (NSWindow *) frontDocumentWindow +{ + for (NSWindow *aWindow in [self orderedWindows]) { + if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { + return aWindow; + } + } + + return nil; +} + +#pragma mark - #pragma mark IBAction methods /** @@ -337,11 +397,38 @@ return prefsController; } +/** + * Provide a method to retrieve an ordered list of the database + * connection windows currently open in the application. + */ +- (NSArray *) orderedDatabaseConnectionWindows +{ + NSMutableArray *orderedDatabaseConnectionWindows = [NSMutableArray array]; + for (NSWindow *aWindow in [NSApp orderedWindows]) { + if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) [orderedDatabaseConnectionWindows addObject:aWindow]; + } + return orderedDatabaseConnectionWindows; +} + +/** + * Retrieve the frontmost document; returns nil if not found. + */ +- (TableDocument *) frontDocument +{ + for (NSWindow *aWindow in [self orderedWindows]) { + if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { + return [[aWindow windowController] selectedTableDocument]; + } + } + + return nil; +} + #pragma mark - #pragma mark Services menu methods /** - * Passes the query to the last created document + * Passes the query to the frontmost document */ - (void)doPerformQueryService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error { @@ -356,14 +443,14 @@ } // Check if at least one document exists - if (![[[NSDocumentController sharedDocumentController] documents] count]) { + if (![self frontDocument]) { *error = @"No Documents open!"; return; } - // Pass query to last created document - [[[[NSDocumentController sharedDocumentController] documents] objectAtIndex:([[[NSDocumentController sharedDocumentController] documents] count] - 1)] doPerformQueryService:pboardString]; + // Pass query to front document + [[self frontDocument] doPerformQueryService:pboardString]; return; } @@ -446,21 +533,18 @@ #pragma mark Other methods /** - * Override the default open-blank-document methods to automatically connect automatically opened windows. + * Override the default open-blank-document methods to automatically connect automatically opened windows + * if the preference is set */ - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { - TableDocument *firstTableDocument; - // Manually open a new document, setting SPAppController as sender to trigger autoconnection - if (firstTableDocument = [[NSDocumentController sharedDocumentController] makeUntitledDocumentOfType:@"Sequel Pro connection" error:nil]) { - if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault]) { - [firstTableDocument setShouldAutomaticallyConnect:YES]; - } - - [[NSDocumentController sharedDocumentController] addDocument:firstTableDocument]; - [firstTableDocument makeWindowControllers]; - [firstTableDocument showWindows]; + // Manually open a table document + [self newWindow:self]; + + // Set autoconnection if appropriate + if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault]) { + [[self frontDocument] connect]; } // Return NO to the automatic opening @@ -474,16 +558,8 @@ - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { // Only create a new document (without auto-connect) when there are already no documents open. - if ([[[NSDocumentController sharedDocumentController] documents] count] == 0) { - TableDocument *firstTableDocument; - - // Manually open a new document, setting SPAppController as sender to trigger autoconnection - if (firstTableDocument = [[NSDocumentController sharedDocumentController] makeUntitledDocumentOfType:@"Sequel Pro connection" error:nil]) { - [[NSDocumentController sharedDocumentController] addDocument:firstTableDocument]; - [firstTableDocument makeWindowControllers]; - [firstTableDocument showWindows]; - } - + if (![self frontDocument]) { + [self newWindow:self]; return NO; } @@ -620,20 +696,30 @@ */ - (NSArray *)orderedDocuments { - return [[NSDocumentController sharedDocumentController] documents]; + NSMutableArray *orderedDocuments = [NSMutableArray array]; + + for (NSWindow *aWindow in [self orderedWindows]) { + if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { + [orderedDocuments addObjectsFromArray:[[aWindow windowController] documents]]; + } + } + + return orderedDocuments; } /** * Support for 'make new document'. + * TODO: following tab support this has been disabled - need to discuss reimplmenting vs syntax. */ - (void)insertInOrderedDocuments:(TableDocument *)doc { - if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault]) + [self newWindow:self]; +/* if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault]) [doc setShouldAutomaticallyConnect:YES]; [[NSDocumentController sharedDocumentController] addDocument:doc]; [doc makeWindowControllers]; - [doc showWindows]; + [doc showWindows];*/ } /** |