aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPAppController.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-05-23 21:44:59 +0000
committerrowanbeentje <rowan@beent.je>2010-05-23 21:44:59 +0000
commitc661b409eaa0e29d9e012b79e7a66574a554817a (patch)
tree49b310ded9a226a66aa53444c9ba112824854f68 /Source/SPAppController.m
parentb66006f3755c6a57dfc60d4133bc4dc4da0fef56 (diff)
downloadsequelpro-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.m244
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];*/
}
/**