From 2efb532df4a40f18687cf9665ed6f707866fcfed Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sun, 7 Mar 2021 19:38:55 +0100 Subject: [PATCH 01/41] Cleanup SPWindowController --- Interfaces/MainWindow.xib | 50 -- .../BundleSupport/SPBundleCommandRunner.m | 26 +- .../MainViewControllers/SPDatabaseDocument.h | 2 +- .../MainViewControllers/SPDatabaseDocument.m | 64 +- Source/Controllers/SPAppController.m | 60 +- .../SubviewControllers/SPTablesList.m | 2 +- .../Controllers/Window/SPWindowController.h | 20 - .../Controllers/Window/SPWindowController.m | 595 +----------------- .../Window/SPWindowController.swift | 21 +- .../CategoryAdditions/SPWindowAdditions.m | 2 +- Source/Views/SPWindow.m | 12 +- sequel-ace.xcodeproj/project.pbxproj | 4 - 12 files changed, 81 insertions(+), 777 deletions(-) delete mode 100644 Interfaces/MainWindow.xib diff --git a/Interfaces/MainWindow.xib b/Interfaces/MainWindow.xib deleted file mode 100644 index d177e98b0..000000000 --- a/Interfaces/MainWindow.xib +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Source/Controllers/BundleSupport/SPBundleCommandRunner.m b/Source/Controllers/BundleSupport/SPBundleCommandRunner.m index f7e430ae7..b86925188 100644 --- a/Source/Controllers/BundleSupport/SPBundleCommandRunner.m +++ b/Source/Controllers/BundleSupport/SPBundleCommandRunner.m @@ -169,21 +169,19 @@ + (NSString *)runBashCommand:(NSString *)command withEnvironment:(NSDictionary*) databaseDocument = nil; } else { for (NSWindow *window in [NSApp orderedWindows]) { - if ([[[window windowController] class] isKindOfClass:[SPWindowController class]]) { - NSArray *documents = [(SPWindowController *)[window windowController] documents]; - for (SPDatabaseDocument *document in documents) { - // Check if connected - if ([document getConnection]) { - databaseDocument = document; - } else { - databaseDocument = nil; - } - - if (databaseDocument) { - break; - } + if ([[[window windowController] class] isKindOfClass:[SPWindowController class]]) { + // Check if connected + SPDatabaseDocument *document = [(SPWindowController *)[window windowController] selectedTableDocument]; + if ([document getConnection]) { + databaseDocument = document; + } else { + databaseDocument = nil; } - } + + if (databaseDocument) { + break; + } + } } } diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index a0fbda3e1..ec9c57051 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -64,7 +64,7 @@ /** * The SPDatabaseDocument class controls the primary database view window. */ -@interface SPDatabaseDocument : NSObject +@interface SPDatabaseDocument : NSViewController { // IBOutlets IBOutlet SPTablesList *tablesListInstance; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index ff9bfda71..e42086524 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -2934,42 +2934,28 @@ - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)ret for (SPWindowController *windowController in [SPAppDelegate windowControllers]) { // First window is always the currently key window - - NSMutableArray *tabs = [NSMutableArray array]; NSMutableDictionary *win = [NSMutableDictionary dictionary]; - // Loop through all tabs of a given window - NSInteger tabCount = 0; - NSInteger selectedTabItem = 0; - for (SPDatabaseDocument *doc in [windowController documents]) { - - // Skip not connected docs eg if connection controller is displayed (TODO maybe to be improved) - if(![doc mySQLVersion]) continue; - - NSMutableDictionary *tabData = [NSMutableDictionary dictionary]; - if([doc isUntitled]) { - // new bundle file name for untitled docs - NSString *newName = [NSString stringWithFormat:@"%@.%@", [NSString stringWithNewUUID], SPFileExtensionDefault]; - // internal bundle path to store the doc - NSString *filePath = [NSString stringWithFormat:@"%@/Contents/%@", fileName, newName]; - // save it as temporary spf file inside the bundle with save panel options spfDocData_temp - [doc saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; - [doc setIsSavedInBundle:YES]; - [tabData setObject:@NO forKey:@"isAbsolutePath"]; - [tabData setObject:newName forKey:@"path"]; - } else { - // save it to the original location and take the file's spfDocData - [doc saveDocumentWithFilePath:[[doc fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; - [tabData setObject:@YES forKey:@"isAbsolutePath"]; - [tabData setObject:[[doc fileURL] path] forKey:@"path"]; - } - [tabs addObject:tabData]; - if ([windowController selectedTableDocument] == doc) selectedTabItem = tabCount; - tabCount++; + // Skip not connected docs eg if connection controller is displayed (TODO maybe to be improved) + if (![windowController.selectedTableDocument mySQLVersion]) continue; + + NSMutableDictionary *tabData = [NSMutableDictionary dictionary]; + if([windowController.selectedTableDocument isUntitled]) { + // new bundle file name for untitled docs + NSString *newName = [NSString stringWithFormat:@"%@.%@", [NSString stringWithNewUUID], SPFileExtensionDefault]; + // internal bundle path to store the doc + NSString *filePath = [NSString stringWithFormat:@"%@/Contents/%@", fileName, newName]; + // save it as temporary spf file inside the bundle with save panel options spfDocData_temp + [windowController.selectedTableDocument saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; + [windowController.selectedTableDocument setIsSavedInBundle:YES]; + [tabData setObject:@NO forKey:@"isAbsolutePath"]; + [tabData setObject:newName forKey:@"path"]; + } else { + // save it to the original location and take the file's spfDocData + [windowController.selectedTableDocument saveDocumentWithFilePath:[[windowController.selectedTableDocument fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; + [tabData setObject:@YES forKey:@"isAbsolutePath"]; + [tabData setObject:[[windowController.selectedTableDocument fileURL] path] forKey:@"path"]; } - if (![tabs count]) continue; - [win setObject:tabs forKey:@"tabs"]; - [win setObject:[NSNumber numberWithInteger:selectedTabItem] forKey:@"selectedTabIndex"]; [win setObject:NSStringFromRect([[windowController window] frame]) forKey:@"frame"]; [windows addObject:win]; } @@ -3229,7 +3215,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB - (IBAction)openDatabaseInNewTab:(id)sender { // Add a new tab to the window - [self.parentWindowController addNewConnection:self]; + [self.parentWindowController addNewConnection]; // Get the current state NSDictionary *allStateDetails = @{ @@ -3615,17 +3601,10 @@ - (void) updateWindowTitle:(id)sender // Set the titles [parentTabViewItem setLabel:tabTitle]; [parentTabViewItem setColor:tabColor]; - [self.parentWindowController updateTabBar]; if ([self.parentWindowController selectedTableDocument] == self) { [[self.parentWindowController window] setTitle:windowTitle]; } - - // If the sender wasn't the window controller, update other tabs in this window - // for shared pathname updates - if ([sender class] != [SPWindowController class]) { - [self.parentWindowController updateAllTabTitles:self]; - } } /** @@ -5413,9 +5392,6 @@ - (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRec } - // Otherwise position the sheet beneath the tab bar if it's visible - rect.origin.y -= [self.parentWindowController.tabBarControl frame].size.height - 1; - return rect; } diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index d59537dd2..9064e8e02 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -650,7 +650,7 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { // Loop through each defined window in reversed order to reconstruct the last active window for (NSDictionary *window in [[[spfs objectForKey:@"windows"] reverseObjectEnumerator] allObjects]) { // Create a new window controller, and set up a new connection view within it. - SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; + SPWindowController *newWindowController = [[SPWindowController alloc] init]; [self.windowControllers addObject:newWindowController]; NSWindow *newWindow = [newWindowController window]; @@ -713,9 +713,6 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { NSBeep(); } } - - // Select active tab - [newWindowController selectTabAtIndex:[[window objectForKey:@"selectedTabIndex"] intValue]]; } } @@ -922,11 +919,9 @@ - (void)handleEventWithURL:(NSURL*)url processDocument = [self frontDocument]; } else { for (SPWindowController *windowController in self.windowControllers) { - for (SPDatabaseDocument *doc in [windowController documents]) { - if([doc processID] && [[doc processID] isEqualToString:passedProcessID]) { - processDocument = doc; - goto break_loop; - } + if([windowController.selectedTableDocument processID] && [[windowController.selectedTableDocument processID] isEqualToString:passedProcessID]) { + processDocument = windowController.selectedTableDocument; + goto break_loop; } } break_loop: /* breaking two levels of foreach */; @@ -1093,11 +1088,9 @@ - (NSDictionary*)shellEnvironmentForDocument:(NSString*)docUUID { doc = [self frontDocument]; else { for (SPWindowController *windowController in self.windowControllers) { - for(SPDatabaseDocument *d in [windowController documents]) { - if ([d processID] && [[d processID] isEqualToString:docUUID]) { - [env addEntriesFromDictionary:[d shellVariables]]; - goto break_loop; - } + if ([windowController.selectedTableDocument processID] && [[windowController.selectedTableDocument processID] isEqualToString:docUUID]) { + [env addEntriesFromDictionary:[windowController.selectedTableDocument shellVariables]]; + goto break_loop; } } break_loop: /* breaking two levels of foreach */; @@ -1375,23 +1368,20 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende // Iterate through each open window for (SPWindowController *windowController in self.windowControllers) { - // Iterate through each document in the window - for (SPDatabaseDocument *doc in [windowController documents]) { - // Kill any BASH commands which are currently active - for (NSDictionary *cmd in [doc runningActivities]) { - NSInteger pid = [[cmd objectForKey:@"pid"] integerValue]; - NSTask *killTask = [[NSTask alloc] init]; - - [killTask setLaunchPath:@"/bin/sh"]; - [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", (long)pid], nil]]; - [killTask launch]; - [killTask waitUntilExit]; - } + // Kill any BASH commands which are currently active + for (NSDictionary *cmd in [windowController.selectedTableDocument runningActivities]) { + NSInteger pid = [[cmd objectForKey:@"pid"] integerValue]; + NSTask *killTask = [[NSTask alloc] init]; + + [killTask setLaunchPath:@"/bin/sh"]; + [killTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"kill -9 -%ld", (long)pid], nil]]; + [killTask launch]; + [killTask waitUntilExit]; + } - // If the connection view is active, mark the favourites for saving - if (![doc getConnection]) { - shouldSaveFavorites = YES; - } + // If the connection view is active, mark the favourites for saving + if (![windowController.selectedTableDocument getConnection]) { + shouldSaveFavorites = YES; } } @@ -1473,13 +1463,11 @@ - (NSArray *)orderedDocuments { NSMutableArray *orderedDocuments = [NSMutableArray array]; - for (NSWindow *aWindow in [self orderedWindows]) - { + for (NSWindow *aWindow in [self orderedWindows]) { if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { - [orderedDocuments addObjectsFromArray:[[aWindow windowController] documents]]; + [orderedDocuments addObject:[(SPWindowController *)[aWindow windowController] selectedTableDocument]]; } } - return orderedDocuments; } @@ -1545,7 +1533,7 @@ - (SPWindowController *)newWindowController { 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"]; + SPWindowController *newWindowController = [[SPWindowController alloc] init]; newWindowController.delegate = self; NSWindow *newWindow = [newWindowController window]; @@ -1593,7 +1581,7 @@ - (IBAction)newTab:(id)sender { if ([[self.activeWindowController window] isMiniaturized]) { [[self.activeWindowController window] deminiaturize:self]; } - [self.activeWindowController addNewConnection:self]; + [self.activeWindowController addNewConnection]; } } diff --git a/Source/Controllers/SubviewControllers/SPTablesList.m b/Source/Controllers/SubviewControllers/SPTablesList.m index 89c1e330b..921f0fabe 100644 --- a/Source/Controllers/SubviewControllers/SPTablesList.m +++ b/Source/Controllers/SubviewControllers/SPTablesList.m @@ -717,7 +717,7 @@ - (IBAction)truncateTable:(id)sender { - (IBAction)openTableInNewTab:(id)sender { // Add a new tab to the window - [[tableDocumentInstance parentWindowController] addNewConnection:self]; + [[tableDocumentInstance parentWindowController] addNewConnection]; [self _duplicateConnectionToFrontTab]; } diff --git a/Source/Controllers/Window/SPWindowController.h b/Source/Controllers/Window/SPWindowController.h index 00503a5cf..b37f3220c 100644 --- a/Source/Controllers/Window/SPWindowController.h +++ b/Source/Controllers/Window/SPWindowController.h @@ -30,38 +30,18 @@ @import AppKit; -@class PSMTabBarControl; @class SPDatabaseDocument; @protocol SPWindowControllerDelegate; @interface SPWindowController : NSWindowController -{ - NSClipView *titleBarLineHidingView; - NSMutableArray *managedDatabaseConnections; -} @property (nonatomic, strong) NSMenuItem *closeWindowMenuItem; @property (nonatomic, strong) NSMenuItem *closeTabMenuItem; @property (nonatomic, weak) id delegate; -@property (nonatomic, strong) IBOutlet NSTabView *tabView; -@property (nonatomic, strong) IBOutlet PSMTabBarControl *tabBarControl; @property (readonly, strong) SPDatabaseDocument *selectedTableDocument; -// Database connection management -- (IBAction)addNewConnection:(id)sender; -- (IBAction)moveSelectedTabInNewWindow:(id)sender; - - (SPDatabaseDocument *)addNewConnection; -- (void)updateSelectedTableDocument; -- (void)updateAllTabTitles:(id)sender; -- (IBAction)closeTab:(id)sender; -- (IBAction)selectNextDocumentTab:(id)sender; -- (IBAction)selectPreviousDocumentTab:(id)sender; -- (NSArray *)documents; -- (void)selectTabAtIndex:(NSInteger)index; -- (void)updateTabBar; - @end @protocol SPWindowControllerDelegate diff --git a/Source/Controllers/Window/SPWindowController.m b/Source/Controllers/Window/SPWindowController.m index 36725f9d5..1e83ed84d 100644 --- a/Source/Controllers/Window/SPWindowController.m +++ b/Source/Controllers/Window/SPWindowController.m @@ -43,18 +43,11 @@ @interface SPWindowController () -- (void)_setUpTabBar; -- (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem; - (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc; - (void)_selectedTableDocumentDeallocd:(NSNotification *)notification; @property (readwrite, strong) SPDatabaseDocument *selectedTableDocument; -#pragma mark - SPWindowControllerDelegate - -- (void)tabDragStarted:(id)sender; -- (void)tabDragStopped:(id)sender; - @end @implementation SPWindowController @@ -62,8 +55,16 @@ @implementation SPWindowController #pragma mark - #pragma mark Initialisation -- (void)awakeFromNib { - [super awakeFromNib]; +- (instancetype)init { + SPWindow *newWindow = [[SPWindow alloc] init]; + if (self = [self initWithWindow:newWindow]) { + + } + return self; +} + +- (void)windowDidLoad { + [super windowDidLoad]; [self setupAppearance]; [self setupConstraints]; @@ -78,21 +79,11 @@ - (void)awakeFromNib { // controller apply cascading after frame autosaving. [self setShouldCascadeWindows:NO]; - // Initialise the managed database connections array - managedDatabaseConnections = [[NSMutableArray alloc] init]; - - [self _setUpTabBar]; - // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. NSMenu *mainMenu = [NSApp mainMenu]; _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; - // Register for drag start and stop notifications - used to show/hide tab bars - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self selector:@selector(tabDragStarted:) name:PSMTabDragDidBeginNotification object:nil]; - [nc addObserver:self selector:@selector(tabDragStopped:) name:PSMTabDragDidEndNotification object:nil]; - // Because we are a document-based app we automatically adopt window restoration on 10.7+. // However that causes a race condition with our own window setup code. // Remove this when we actually support restoration. @@ -104,202 +95,34 @@ - (void)awakeFromNib { #pragma mark - #pragma mark Database connection management -/** - * Add a new database connection to the window, in a tab view. - */ -- (IBAction)addNewConnection:(id)sender -{ - [self addNewConnection]; -} - - (SPDatabaseDocument *)addNewConnection { // Create a new database connection view SPDatabaseDocument *databaseDocument = [[SPDatabaseDocument alloc] initWithWindowController:self]; + self.contentViewController = databaseDocument; - // Set up a new tab with the connection view as the identifier, add the view, and add it to the tab view - NSTabViewItem *newItem = [[NSTabViewItem alloc] initWithIdentifier:databaseDocument]; - - if(newItem != nil){ - [newItem setView:[databaseDocument databaseView]]; - [self.tabView addTabViewItem:newItem]; - [self.tabView selectTabViewItem:newItem]; - [databaseDocument setParentTabViewItem:newItem]; - - // Tell the new database connection view to set up the window and update titles - [databaseDocument didBecomeActiveTabInWindow]; - [databaseDocument updateWindowTitle:self]; - - // Bind the tab bar's progress display to the document - [self _updateProgressIndicatorForItem:newItem]; - } - else{ - [NSAlert createWarningAlertWithTitle:NSLocalizedString(@"New Connection Error", @"New Connection Error") message:NSLocalizedString(@"Failed to create new database connection window. Please restart Sequel Ace and try again.", @"New Connection Error informative message") callback:nil]; - SPLog(@"Failed to create new NSTabViewItem. databaseDocument = %@", databaseDocument); - } + // Tell the new database connection view to set up the window and update titles + [databaseDocument didBecomeActiveTabInWindow]; + [databaseDocument updateWindowTitle:self]; return databaseDocument; } -/** - * Update the currently selected connection view - */ -- (void)updateSelectedTableDocument -{ - [self _switchOutSelectedTableDocument:[[self.tabView selectedTabViewItem] databaseDocument]]; - - [self.selectedTableDocument didBecomeActiveTabInWindow]; -} - -/** - * Ask all the connection views to update their titles. - * As tab titles depend on the currently selected tab, changes - * within each tab may require other tabs to update their titles. - * If the sender is a tab, that tab is skipped when updating titles. - */ -- (void)updateAllTabTitles:(id)sender -{ - for (NSTabViewItem *eachItem in [self.tabView tabViewItems]) - { - SPDatabaseDocument *eachDocument = [eachItem databaseDocument]; - - if (eachDocument != sender) { - [eachDocument updateWindowTitle:self]; - } - } -} - /** * Close the current tab, or if it's the last in the window, the window. */ - (IBAction)closeTab:(id)sender { - // If there are multiple tabs, close the front tab. - if ([self.tabView numberOfTabViewItems] > 1) { - // Return if the selected tab shouldn't be closed - if (![self.selectedTableDocument parentTabShouldClose]) { - return; - } - if([[self.tabView tabViewItems] containsObject:[self.tabView selectedTabViewItem]] == YES){ - [self.tabView removeTabViewItem:[self.tabView selectedTabViewItem]]; - } - } - else { + //trying to close the window will itself call parentTabShouldClose for all tabs in windowShouldClose: [[self window] performClose:self]; [self.delegate windowControllerDidClose:self]; - } -} - -/** - * Select next tab; if last select first one. - */ -- (IBAction) selectNextDocumentTab:(id)sender -{ - if ([self.tabView indexOfTabViewItem:[self.tabView selectedTabViewItem]] == [self.tabView numberOfTabViewItems] - 1) { - [self.tabView selectFirstTabViewItem:nil]; - } - else { - [self.tabView selectNextTabViewItem:nil]; - } -} - -/** - * Select previous tab; if first select last one. - */ -- (IBAction) selectPreviousDocumentTab:(id)sender -{ - if ([self.tabView indexOfTabViewItem:[self.tabView selectedTabViewItem]] == 0) { - [self.tabView selectLastTabViewItem:nil]; - } - else { - [self.tabView selectPreviousTabViewItem:nil]; - } -} - -/** - * Move the currently selected tab to a new window. - */ -- (IBAction)moveSelectedTabInNewWindow:(id)sender { - static NSPoint cascadeLocation = {.x = 0, .y = 0}; - - NSTabViewItem *selectedTabViewItem = [self.tabView selectedTabViewItem]; - SPDatabaseDocument *selectedDocument = [selectedTabViewItem databaseDocument]; - PSMTabBarCell *selectedCell = [[self.tabBarControl cells] objectAtIndex:[self.tabView indexOfTabViewItem:selectedTabViewItem]]; - - SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; - [self.delegate windowControllerDidCreateNewWindowController:newWindowController]; - NSWindow *newWindow = [newWindowController window]; - - CGFloat toolbarHeight = 0; - - if ([[[self window] toolbar] isVisible]) { - NSRect innerFrame = [NSWindow contentRectForFrameRect:[[self window] frame] styleMask:[[self window] styleMask]]; - toolbarHeight = innerFrame.size.height - [[[self window] contentView] frame].size.height; - } - - // Set the new window position and size - NSRect targetWindowFrame = [[self window] frame]; - targetWindowFrame.size.height -= toolbarHeight; - [newWindow setFrame:targetWindowFrame display:NO]; - - // Cascade according to the statically stored cascade location. - cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; - - // Set the window controller as the window's delegate - [newWindow setDelegate:newWindowController]; - - // Set window title - [newWindow setTitle:[[selectedDocument parentWindowControllerWindow] title]]; - - // New window's self.tabBarControl control - PSMTabBarControl *control = newWindowController.tabBarControl; - - // Add the selected tab to the new window - [[control cells] insertObject:selectedCell atIndex:0]; - - // Remove 'isProcessing' observer from old windowController - [selectedDocument removeObserver:self forKeyPath:@"isProcessing"]; - - // Update new 'isProcessing' observer and bind the new tab bar's progress display to the document - [self _updateProgressIndicatorForItem:selectedTabViewItem]; - - //remove the tracking rects and bindings registered on the old tab - [self.tabBarControl removeTrackingRect:[selectedCell closeButtonTrackingTag]]; - [self.tabBarControl removeTrackingRect:[selectedCell cellTrackingTag]]; - [self.tabBarControl removeTabForCell:selectedCell]; - - //rebind the selected cell to the new control - [control bindPropertiesForCell:selectedCell andTabViewItem:selectedTabViewItem]; - - [selectedCell setCustomControlView:control]; - - if([[self.tabBarControl.tabView tabViewItems] containsObject:[selectedCell representedObject]] == YES){ - [[self.tabBarControl tabView] removeTabViewItem:[selectedCell representedObject]]; - } - [[control tabView] addTabViewItem:selectedTabViewItem]; - - // Make sure the new tab is set in the correct position by forcing an update - [self.tabBarControl update]; - - // Update self.tabBarControl of the new window - [newWindowController tabView:[self.tabBarControl tabView] didDropTabViewItem:[selectedCell representedObject] inTabBar:control]; - - [newWindow makeKeyAndOrderFront:nil]; } /** * Menu item validation. */ -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem -{ - // Select Next/Previous/Move Tab - if ([menuItem action] == @selector(selectPreviousDocumentTab:) || - [menuItem action] == @selector(selectNextDocumentTab:) || - [menuItem action] == @selector(moveSelectedTabInNewWindow:)) - { - return ([self.tabView numberOfTabViewItems] != 1); - } +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { // See if the front document blocks validation of this item if (![self.selectedTableDocument validateMenuItem:menuItem]) return NO; @@ -307,30 +130,6 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem return YES; } -/** - * Retrieve the documents associated with this window. - */ -- (NSArray *)documents { - NSMutableArray *documentsArray = [NSMutableArray array]; - for (NSTabViewItem *eachItem in [self.tabView tabViewItems]) { - [documentsArray safeAddObject:[eachItem databaseDocument]]; - } - return documentsArray; -} - -/** - * Select tab at index. - */ -- (void)selectTabAtIndex:(NSInteger)index -{ - if ([[self.tabBarControl cells] count] > 0 && [[self.tabBarControl cells] count] > (NSUInteger)index) { - [self.tabView selectTabViewItemAtIndex:index]; - } - else if ([[self.tabBarControl cells] count]) { - [self.tabView selectTabViewItemAtIndex:0]; - } -} - /** * Opens the current connection in a new tab, but only if it's already connected. */ @@ -341,21 +140,6 @@ - (void)openDatabaseInNewTab } } -#pragma mark - -#pragma mark Tab Bar -- (void)updateTabBar -{ - BOOL collapse = NO; - - if (self.selectedTableDocument.getConnection) { - if (self.selectedTableDocument.connectionController.colorIndex != -1) { - collapse = YES; - } - } - - [self.tabBarControl update]; -} - #pragma mark - #pragma mark First responder forwarding to active tab @@ -395,67 +179,9 @@ - (BOOL)respondsToSelector:(SEL)theSelector return ([super respondsToSelector:theSelector] || [self.selectedTableDocument respondsToSelector:theSelector]); } -/** - * When receiving an update for a bound value - an observed value on the - * document - ask the tab bar control to redraw as appropriate. - */ -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - [self.tabBarControl update]; -} - #pragma mark - #pragma mark Private API -/** - * Set up the window's tab bar. - */ -- (void)_setUpTabBar -{ - [self.tabBarControl setStyleNamed:@"SequelPro"]; - [self.tabBarControl setCanCloseOnlyTab:NO]; - [self.tabBarControl setShowAddTabButton:YES]; - [self.tabBarControl setSizeCellsToFit:NO]; - [self.tabBarControl setCellMinWidth:100]; - [self.tabBarControl setCellMaxWidth:25000]; - [self.tabBarControl setCellOptimumWidth:25000]; - [self.tabBarControl setSelectsTabsOnMouseDown:YES]; - [self.tabBarControl setCreatesTabOnDoubleClick:YES]; - [self.tabBarControl setTearOffStyle:PSMTabBarTearOffAlphaWindow]; - [self.tabBarControl setUsesSafariStyleDragging:YES]; - - // Hook up add tab button - [self.tabBarControl setCreateNewTabTarget:self]; - [self.tabBarControl setCreateNewTabAction:@selector(addNewConnection:)]; - - // Set the double click target and action - [self.tabBarControl setDoubleClickTarget:self]; - [self.tabBarControl setDoubleClickAction:@selector(openDatabaseInNewTab)]; -} - -/** - * Binds a tab bar item's progress indicator to the represented tableDocument. - */ -- (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem -{ - PSMTabBarCell *theCell = [[self.tabBarControl cells] objectAtIndex:[self.tabView indexOfTabViewItem:theItem]]; - - [[theCell indicator] setControlSize:NSControlSizeSmall]; - - SPDatabaseDocument *theDocument = [theItem databaseDocument]; - - [[theCell indicator] setHidden:NO]; - - NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; - - [bindingOptions setObject:NSNegateBooleanTransformerName forKey:@"NSValueTransformerName"]; - - [[theCell indicator] bind:@"animate" toObject:theDocument withKeyPath:@"isProcessing" options:nil]; - [[theCell indicator] bind:@"hidden" toObject:theDocument withKeyPath:@"isProcessing" options:bindingOptions]; - - [theDocument addObserver:self forKeyPath:@"isProcessing" options:0 context:nil]; -} - - (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc { NSAssert([NSThread isMainThread], @"Switching the selectedTableDocument via a background thread is not supported!"); @@ -474,8 +200,6 @@ - (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc [nc addObserver:self selector:@selector(_selectedTableDocumentDeallocd:) name:SPDocumentWillCloseNotification object:newDoc]; self.selectedTableDocument = newDoc; } - - [self updateTabBar]; } - (void)_selectedTableDocumentDeallocd:(NSNotification *)notification @@ -483,293 +207,6 @@ - (void)_selectedTableDocumentDeallocd:(NSNotification *)notification [self _switchOutSelectedTableDocument:nil]; } -#pragma mark - -#pragma mark Tab view delegate methods - -/** - * Called when a tab item is about to be selected. - */ -- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - [self.selectedTableDocument willResignActiveTabInWindow]; -} - -/** - * Called when a tab item was selected. - */ -- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) return; - - [self _switchOutSelectedTableDocument:[tabViewItem databaseDocument]]; - [self.selectedTableDocument didBecomeActiveTabInWindow]; - - if ([[self window] isKeyWindow]) { - [self.selectedTableDocument tabDidBecomeKey]; - } - - [self updateAllTabTitles:self]; -} - -/** - * Called to determine whether a tab view item can be closed - * - * Note: This is ONLY called when using the "X" button on the tab itself. - */ -- (BOOL)tabView:(NSTabView *)aTabView shouldCloseTabViewItem:(NSTabViewItem *)tabViewItem -{ - SPDatabaseDocument *theDocument = [tabViewItem databaseDocument]; - - if (![theDocument parentTabShouldClose]) { - return NO; - } - return YES; -} - -/** - * Called after a tab view item is closed. - */ -- (void)tabView:(NSTabView *)aTabView didCloseTabViewItem:(NSTabViewItem *)tabViewItem -{ - SPDatabaseDocument *theDocument = [tabViewItem databaseDocument]; - - [theDocument removeObserver:self forKeyPath:@"isProcessing"]; - [theDocument parentTabDidClose]; -} - -/** - * Called to allow dragging of tab view items - */ -- (BOOL)tabView:(NSTabView *)aTabView shouldDragTabViewItem:(NSTabViewItem *)tabViewItem fromTabBar:(PSMTabBarControl *)tabBarControl -{ - return YES; -} - -/** - * Called when a tab finishes a drop. This is called with the new tabView. - */ -- (void)tabView:(NSTabView*)aTabView didDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl -{ - SPDatabaseDocument *draggedDocument = [tabViewItem databaseDocument]; - - // Grab a reference to the old window - NSWindow *draggedFromWindow = [draggedDocument parentWindowControllerWindow]; - - // If the window changed, perform additional processing. - if (draggedFromWindow != [tabBarControl window]) { - - // Update the old window, ensuring the toolbar is cleared to prevent issues with toolbars in multiple windows - [draggedFromWindow setToolbar:nil]; - [[draggedFromWindow windowController] updateSelectedTableDocument]; - - // Update the item's document's window and controller - [draggedDocument willResignActiveTabInWindow]; - [draggedDocument updateParentWindowController:[[tabBarControl window] windowController]]; - [draggedDocument didBecomeActiveTabInWindow]; - - // Update window controller's active tab, and update the document's isProcessing observation - [[[tabBarControl window] windowController] updateSelectedTableDocument]; - [draggedDocument removeObserver:[draggedFromWindow windowController] forKeyPath:@"isProcessing"]; - [[[tabBarControl window] windowController] _updateProgressIndicatorForItem:tabViewItem]; - } - - // Check the window and move it to front if it's key (eg for new window creation) - if ([[tabBarControl window] isKeyWindow]) { - [[tabBarControl window] orderFront:self]; - } - - // workaround bug where "source list" table views are broken in the new window. See https://github.com/sequelpro/sequelpro/issues/2863 - SPWindowController *newWindowController = tabBarControl.window.windowController; - newWindowController.selectedTableDocument.connectionController.favoritesOutlineView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular; - newWindowController.selectedTableDocument.dbTablesTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0)), dispatch_get_main_queue(), ^{ - newWindowController.selectedTableDocument.dbTablesTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleSourceList; - newWindowController.selectedTableDocument.connectionController.favoritesOutlineView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleSourceList; - }); -} - -/** - * Respond to dragging events entering the tab in the tab bar. - * Allows custom behaviours - for example, if dragging text, switch to the custom - * query view. - */ -- (void)draggingEvent:(id )dragEvent enteredTabBar:(PSMTabBarControl *)tabBarControl tabView:(NSTabViewItem *)tabViewItem -{ - SPDatabaseDocument *theDocument = [tabViewItem databaseDocument]; - - if (![theDocument isCustomQuerySelected] && [[[dragEvent draggingPasteboard] types] indexOfObject:NSStringPboardType] != NSNotFound) - { - [theDocument viewQuery:self]; - } -} - -/** - * Show tooltip for a tab view item. - */ -- (NSString *)tabView:(NSTabView *)aTabView toolTipForTabViewItem:(NSTabViewItem *)tabViewItem -{ - NSInteger tabIndex = [self.tabView indexOfTabViewItem:tabViewItem]; - - if ([[self.tabBarControl cells] count] < (NSUInteger)tabIndex) return @""; - - PSMTabBarCell *theCell = [[self.tabBarControl cells] objectAtIndex:tabIndex]; - - // If cell is selected show tooltip if truncated only - if ([theCell tabState] & PSMTab_SelectedMask) { - - CGFloat cellWidth = [theCell width]; - CGFloat titleWidth = [theCell stringSize].width; - CGFloat closeButtonWidth = 0; - - if ([theCell hasCloseButton]) - closeButtonWidth = [theCell closeButtonRectForFrame:[theCell frame]].size.width; - - if (titleWidth > cellWidth - closeButtonWidth) { - return [theCell title]; - } - - return @""; - } - // if cell is not selected show full title plus MySQL version is enabled as tooltip - else { - return [[tabViewItem databaseDocument] tabTitleForTooltip]; - } -} - -/** - * Allow window closing of the last tab item. - */ -- (void)tabView:(NSTabView *)aTabView closeWindowForLastTabViewItem:(NSTabViewItem *)tabViewItem -{ - [[aTabView window] close]; -} - -/** - * When dragging a tab off a tab bar, add a shadow to the drag window. - */ -- (void)tabViewDragWindowCreated:(NSWindow *)dragWindow -{ - [dragWindow setHasShadow:YES]; -} - -/** - * Allow dragging and dropping of tabs to any position, including out of a tab bar - * to create a new window. - */ -- (BOOL)tabView:(NSTabView*)aTabView shouldDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl -{ - return YES; -} - -/** - * When a tab is dragged off a tab bar, create a new window containing a new - * (empty) tab bar to hold it. - */ -- (PSMTabBarControl *)tabView:(NSTabView *)aTabView newTabBarForDraggedTabViewItem:(NSTabViewItem *)tabViewItem atPoint:(NSPoint)point { - // Create the new window controller, with no tabs - SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; - [self.delegate windowControllerDidCreateNewWindowController:newWindowController]; - NSWindow *newWindow = [newWindowController window]; - - CGFloat toolbarHeight = 0; - - if ([[[self window] toolbar] isVisible]) { - NSRect innerFrame = [NSWindow contentRectForFrameRect:[[self window] frame] styleMask:[[self window] styleMask]]; - toolbarHeight = innerFrame.size.height - [[[self window] contentView] frame].size.height; - } - - // Adjust the positioning as appropriate - point.y += toolbarHeight + kPSMTabBarControlHeight; - - // Set the new window position and size - NSRect targetWindowFrame = [[self window] frame]; - targetWindowFrame.size.height -= toolbarHeight; - [newWindow setFrame:targetWindowFrame display:NO]; - [newWindow setFrameTopLeftPoint:point]; - - // Set the window controller as the window's delegate - [newWindow setDelegate:newWindowController]; - - // Set window title - [newWindow setTitle:[[[tabViewItem databaseDocument] parentWindowControllerWindow] title]]; - - // Return the window's tab bar - return newWindowController.tabBarControl; -} - -/** - * When dragging a tab off the tab bar, return an image so that a - * drag placeholder can be displayed. - */ -- (NSImage *)tabView:(NSTabView *)aTabView imageForTabViewItem:(NSTabViewItem *)tabViewItem offset:(NSSize *)offset styleMask:(NSUInteger *)styleMask -{ - NSImage *viewImage = [[NSImage alloc] init]; - - // Capture an image of the entire window - CGImageRef windowImage = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, (unsigned int)[[self window] windowNumber], kCGWindowImageBoundsIgnoreFraming); - NSBitmapImageRep *viewRep = [[NSBitmapImageRep alloc] initWithCGImage:windowImage]; - [viewRep setSize:[[self window] frame].size]; - [viewImage addRepresentation:viewRep]; - - // Calculate the titlebar+toolbar height - CGFloat contentViewOffsetY = [[self window] frame].size.height - [[[self window] contentView] frame].size.height; - offset->height = contentViewOffsetY + [self.tabBarControl frame].size.height; - - // Draw over the tab bar area - [viewImage lockFocus]; - [[NSColor windowBackgroundColor] set]; - NSRectFill([self.tabBarControl frame]); - [viewImage unlockFocus]; - - // Draw the tab bar background in the tab bar area - [viewImage lockFocus]; - NSRect tabFrame = [self.tabBarControl frame]; - [[NSColor windowBackgroundColor] set]; - NSRectFill(tabFrame); - - // Draw the background flipped, which is actually the right way up - NSAffineTransform *transform = [NSAffineTransform transform]; - - [transform translateXBy:0.0f yBy:[[[self window] contentView] frame].size.height]; - [transform scaleXBy:1.0f yBy:-1.0f]; - - [transform concat]; - [(id )[(PSMTabBarControl *)[aTabView delegate] style] drawBackgroundInRect:tabFrame]; - - [viewImage unlockFocus]; - - return viewImage; -} - -/** - * Displays the current tab's context menu. - */ -- (NSMenu *)tabView:(NSTabView *)aTabView menuForTabViewItem:(NSTabViewItem *)tabViewItem -{ - NSMenu *menu = [[NSMenu alloc] init]; - - [menu addItemWithTitle:NSLocalizedString(@"Close Tab", @"close tab context menu item") action:@selector(closeTab:) keyEquivalent:@""]; - [menu insertItem:[NSMenuItem separatorItem] atIndex:1]; - [menu addItemWithTitle:NSLocalizedString(@"Open in New Tab", @"open connection in new tab context menu item") action:@selector(openDatabaseInNewTab:) keyEquivalent:@""]; - - return menu; -} - -/** - * When tab drags start, show all the tab bars. This allows adding tabs to windows - * containing only one tab - where the bar is normally hidden. - */ -- (void)tabDragStarted:(id)sender { - -} - -/** - * When tab drags stop, set tab bars to automatically hide again for only one tab. - */ -- (void)tabDragStopped:(id)sender { - -} - #pragma mark - - (void)dealloc { diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index c9f66014c..a4d414507 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -35,13 +35,8 @@ extension SPWindowController: NSWindowDelegate { /// - Parameter sender: NSWindow instance /// - Returns: true or false public func windowShouldClose(_ sender: NSWindow) -> Bool { - for tabItem in tabView.tabViewItems { - guard let document = tabItem.databaseDocument else { - continue - } - if !document.parentTabShouldClose() { - return false - } + if !selectedTableDocument.parentTabShouldClose() { + return false } if let appDelegate = NSApp.delegate as? SPAppController, appDelegate.sessionURL() != nil, appDelegate.windowControllers.count == 1 { @@ -52,12 +47,6 @@ extension SPWindowController: NSWindowDelegate { return true } - public func windowWillClose(_ notification: Notification) { - tabView.tabViewItems.forEach { - tabView.removeTabViewItem($0) - } - } - public func windowDidBecomeKey(_ notification: Notification) { selectedTableDocument.tabDidBecomeKey() @@ -80,10 +69,4 @@ extension SPWindowController: NSWindowDelegate { closeWindowMenuItem.title = NSLocalizedString("Close", comment: "Close menu item") closeWindowMenuItem.keyEquivalentModifierMask = .command } - - public func windowDidResize(_ notification: Notification) { - tabView.tabViewItems.forEach { - $0.databaseDocument?.tabDidResize() - } - } } diff --git a/Source/Other/CategoryAdditions/SPWindowAdditions.m b/Source/Other/CategoryAdditions/SPWindowAdditions.m index 0c5718b38..e29490ee0 100644 --- a/Source/Other/CategoryAdditions/SPWindowAdditions.m +++ b/Source/Other/CategoryAdditions/SPWindowAdditions.m @@ -85,7 +85,7 @@ - (void)resizeForContentView:(NSView *)view */ - (void)swipeWithEvent:(NSEvent *)event { - if (![[self delegate] isKindOfClass:[SPWindowController class]] || ![[(SPWindowController *)[self delegate] documents] count]) return; + if (![[self delegate] isKindOfClass:[SPWindowController class]]) return; id frontDoc = [(SPWindowController *)[self delegate] selectedTableDocument]; diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index 37ab72c1f..af42157e0 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -101,16 +101,14 @@ - (void) sendEvent:(NSEvent *)theEvent case '}': if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) { - if ([[self windowController] respondsToSelector:@selector(selectNextDocumentTab:)]) - [[self windowController] selectNextDocumentTab:self]; + // TODO: Tabs switching return; } break; case '{': if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) { - if ([[self windowController] respondsToSelector:@selector(selectPreviousDocumentTab:)]) - [[self windowController] selectPreviousDocumentTab:self]; + // TODO: Tabs switching return; } break; @@ -119,16 +117,14 @@ - (void) sendEvent:(NSEvent *)theEvent case NSRightArrowFunctionKey: if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) { - if ([[self windowController] respondsToSelector:@selector(selectNextDocumentTab:)]) - [[self windowController] selectNextDocumentTab:self]; + // TODO: Tabs switching return; } break; case NSLeftArrowFunctionKey: if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) { - if ([[self windowController] respondsToSelector:@selector(selectPreviousDocumentTab:)]) - [[self windowController] selectPreviousDocumentTab:self]; + // TODO: Tabs switching return; } break; diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index 176dbca86..a8058a509 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -291,7 +291,6 @@ 51BC14F825BE135500F1CDC9 /* SPWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */; }; 51BC150125BE138700F1CDC9 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 51BC150025BE138700F1CDC9 /* SnapKit */; }; 51BC150625BE13C400F1CDC9 /* NSViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC150525BE13C400F1CDC9 /* NSViewExtension.swift */; }; - 51BC150E25BE1EB100F1CDC9 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51BC150D25BE1EB100F1CDC9 /* MainWindow.xib */; }; 51C4626D254ED02500F63E70 /* UserDefaultsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C4626C254ED02500F63E70 /* UserDefaultsExtension.swift */; }; 51C6288C24D196E8006491E9 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C8597B24C8A31400A8C7C4 /* StringExtension.swift */; }; 51C8597C24C8A31400A8C7C4 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C8597B24C8A31400A8C7C4 /* StringExtension.swift */; }; @@ -922,7 +921,6 @@ 51BB3E0425AEF0D7005AAE44 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPWindowController.swift; sourceTree = ""; }; 51BC150525BE13C400F1CDC9 /* NSViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSViewExtension.swift; sourceTree = ""; }; - 51BC150D25BE1EB100F1CDC9 /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 51C4626C254ED02500F63E70 /* UserDefaultsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtension.swift; sourceTree = ""; }; 51C8597B24C8A31400A8C7C4 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; 51CD0BBE258D06D7009E2484 /* PrintAccessory.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PrintAccessory.xib; sourceTree = ""; }; @@ -2107,7 +2105,6 @@ 51CD0BC9258D06D8009E2484 /* ImportAccessory.xib */, 51CD0BC4258D06D7009E2484 /* IndexesView.xib */, 51CD0BCA258D06D8009E2484 /* MainMenu.xib */, - 51BC150D25BE1EB100F1CDC9 /* MainWindow.xib */, 51CD0BC7258D06D8009E2484 /* Navigator.xib */, 51CD0BC0258D06D7009E2484 /* Preferences.xib */, 51CD0BBE258D06D7009E2484 /* PrintAccessory.xib */, @@ -2943,7 +2940,6 @@ 5135160425935699001E4533 /* TabNewMetalRollover.png in Resources */, 51CD0BEA258D06D8009E2484 /* DatabaseServerVariables.xib in Resources */, 582E9487168380D6003459FD /* sync_arrows_05.png in Resources */, - 51BC150E25BE1EB100F1CDC9 /* MainWindow.xib in Resources */, 5135161425935699001E4533 /* AquaTabCloseDirty_Front.png in Resources */, 582E9488168380D6003459FD /* sync_arrows_06.png in Resources */, 5135160225935699001E4533 /* SequelProTabDirty_Pressed@2x.png in Resources */, From 2da36782a676b32fbae9cfe4a6fd309709c5f9fd Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sun, 7 Mar 2021 20:51:53 +0100 Subject: [PATCH 02/41] Remove tab bar controller --- Frameworks/PSMTabBar/Images/AddTabButton.png | Bin 141 -> 0 bytes .../PSMTabBar/Images/AddTabButtonPushed.png | Bin 116 -> 0 bytes .../PSMTabBar/Images/AddTabButtonRollover.png | Bin 116 -> 0 bytes Frameworks/PSMTabBar/Images/AdiumGradient.png | Bin 84 -> 0 bytes .../Images/AquaTabCloseDirty_Front.png | Bin 271 -> 0 bytes .../AquaTabCloseDirty_Front_Pressed.png | Bin 271 -> 0 bytes .../AquaTabCloseDirty_Front_Rollover.png | Bin 276 -> 0 bytes .../PSMTabBar/Images/AquaTabClose_Front.png | Bin 286 -> 0 bytes .../Images/AquaTabClose_Front_Pressed.png | Bin 289 -> 0 bytes .../Images/AquaTabClose_Front_Rollover.png | Bin 296 -> 0 bytes Frameworks/PSMTabBar/Images/AquaTabNew.png | Bin 371 -> 0 bytes .../PSMTabBar/Images/AquaTabNewPressed.png | Bin 380 -> 0 bytes .../PSMTabBar/Images/AquaTabNewRollover.png | Bin 380 -> 0 bytes .../PSMTabBar/Images/AquaTabsBackground.png | Bin 344 -> 0 bytes Frameworks/PSMTabBar/Images/AquaTabsDown.png | Bin 153 -> 0 bytes .../PSMTabBar/Images/AquaTabsDownGraphite.png | Bin 240 -> 0 bytes .../PSMTabBar/Images/AquaTabsDownNonKey.png | Bin 166 -> 0 bytes .../PSMTabBar/Images/AquaTabsSeparator.png | Bin 106 -> 0 bytes .../Images/AquaTabsSeparatorDown.png | Bin 149 -> 0 bytes .../PSMTabBar/Images/SequelProTabDirty.png | Bin 185 -> 0 bytes .../PSMTabBar/Images/SequelProTabDirty@2x.png | Bin 307 -> 0 bytes .../Images/SequelProTabDirty_Pressed.png | Bin 226 -> 0 bytes .../Images/SequelProTabDirty_Pressed@2x.png | Bin 415 -> 0 bytes .../Images/SequelProTabDirty_Rollover.png | Bin 226 -> 0 bytes .../Images/SequelProTabDirty_Rollover@2x.png | Bin 415 -> 0 bytes .../PSMTabBar/Images/TabClose_Dirty.png | Bin 262 -> 0 bytes .../Images/TabClose_Dirty_Pressed.png | Bin 255 -> 0 bytes .../Images/TabClose_Dirty_Rollover.png | Bin 255 -> 0 bytes .../PSMTabBar/Images/TabClose_Front.png | Bin 288 -> 0 bytes .../Images/TabClose_Front_Pressed.png | Bin 289 -> 0 bytes .../Images/TabClose_Front_Rollover.png | Bin 287 -> 0 bytes Frameworks/PSMTabBar/Images/TabNewMetal.png | Bin 380 -> 0 bytes .../PSMTabBar/Images/TabNewMetalPressed.png | Bin 380 -> 0 bytes .../PSMTabBar/Images/TabNewMetalRollover.png | Bin 380 -> 0 bytes Frameworks/PSMTabBar/Images/overflowImage.png | Bin 235 -> 0 bytes .../PSMTabBar/Images/overflowImagePressed.png | Bin 229 -> 0 bytes Frameworks/PSMTabBar/Images/pi.png | Bin 559 -> 0 bytes Frameworks/PSMTabBar/NSBezierPath_AMShading.h | 22 - Frameworks/PSMTabBar/NSBezierPath_AMShading.m | 126 -- Frameworks/PSMTabBar/NSString_AITruncation.h | 12 - Frameworks/PSMTabBar/NSString_AITruncation.m | 34 - .../PSMTabBar/NSTabViewItemExtension.swift | 15 - Frameworks/PSMTabBar/PSMOverflowPopUpButton.h | 33 - Frameworks/PSMTabBar/PSMOverflowPopUpButton.m | 148 -- Frameworks/PSMTabBar/PSMProgressIndicator.h | 21 - Frameworks/PSMTabBar/PSMProgressIndicator.m | 27 - Frameworks/PSMTabBar/PSMRolloverButton.h | 31 - Frameworks/PSMTabBar/PSMRolloverButton.m | 173 -- Frameworks/PSMTabBar/PSMTabBarCell.h | 114 -- Frameworks/PSMTabBar/PSMTabBarCell.m | 486 ----- Frameworks/PSMTabBar/PSMTabBarControl.h | 248 --- Frameworks/PSMTabBar/PSMTabBarControl.m | 1709 ----------------- Frameworks/PSMTabBar/PSMTabBarController.h | 44 - Frameworks/PSMTabBar/PSMTabBarController.m | 661 ------- Frameworks/PSMTabBar/PSMTabDragAssistant.h | 103 - Frameworks/PSMTabBar/PSMTabDragAssistant.m | 974 ---------- Frameworks/PSMTabBar/PSMTabDragView.h | 20 - Frameworks/PSMTabBar/PSMTabDragView.m | 60 - Frameworks/PSMTabBar/PSMTabDragWindow.h | 20 - Frameworks/PSMTabBar/PSMTabDragWindow.m | 52 - .../PSMTabBar/PSMTabDragWindowController.h | 34 - .../PSMTabBar/PSMTabDragWindowController.m | 111 -- Frameworks/PSMTabBar/PSMTabStyle.h | 58 - .../PSMTabBar/Styles/PSMSequelProTabStyle.h | 46 - .../PSMTabBar/Styles/PSMSequelProTabStyle.m | 695 ------- Interfaces/DBView.xib | 34 +- .../ConnectionView/SPConnectionController.m | 1 - .../MainViewControllers/SPDatabaseDocument.h | 2 - .../MainViewControllers/SPDatabaseDocument.m | 67 +- Source/Controllers/SPAppController.h | 2 - Source/Controllers/SPAppController.m | 22 +- .../Controllers/Window/SPWindowController.m | 68 +- .../Window/SPWindowController.swift | 10 - Source/Sequel-Ace-Bridging-Header.h | 1 - Source/Views/SPWindow.m | 16 +- sequel-ace.xcodeproj/project.pbxproj | 257 --- 76 files changed, 74 insertions(+), 6483 deletions(-) delete mode 100644 Frameworks/PSMTabBar/Images/AddTabButton.png delete mode 100644 Frameworks/PSMTabBar/Images/AddTabButtonPushed.png delete mode 100644 Frameworks/PSMTabBar/Images/AddTabButtonRollover.png delete mode 100644 Frameworks/PSMTabBar/Images/AdiumGradient.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Pressed.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Rollover.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabClose_Front.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabClose_Front_Pressed.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabClose_Front_Rollover.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabNew.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabNewPressed.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabNewRollover.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsBackground.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsDown.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsDownGraphite.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsDownNonKey.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsSeparator.png delete mode 100644 Frameworks/PSMTabBar/Images/AquaTabsSeparatorDown.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty@2x.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed@2x.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover.png delete mode 100644 Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover@2x.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Dirty.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Dirty_Pressed.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Dirty_Rollover.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Front.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Front_Pressed.png delete mode 100644 Frameworks/PSMTabBar/Images/TabClose_Front_Rollover.png delete mode 100644 Frameworks/PSMTabBar/Images/TabNewMetal.png delete mode 100644 Frameworks/PSMTabBar/Images/TabNewMetalPressed.png delete mode 100644 Frameworks/PSMTabBar/Images/TabNewMetalRollover.png delete mode 100644 Frameworks/PSMTabBar/Images/overflowImage.png delete mode 100644 Frameworks/PSMTabBar/Images/overflowImagePressed.png delete mode 100644 Frameworks/PSMTabBar/Images/pi.png delete mode 100755 Frameworks/PSMTabBar/NSBezierPath_AMShading.h delete mode 100755 Frameworks/PSMTabBar/NSBezierPath_AMShading.m delete mode 100644 Frameworks/PSMTabBar/NSString_AITruncation.h delete mode 100644 Frameworks/PSMTabBar/NSString_AITruncation.m delete mode 100644 Frameworks/PSMTabBar/NSTabViewItemExtension.swift delete mode 100644 Frameworks/PSMTabBar/PSMOverflowPopUpButton.h delete mode 100644 Frameworks/PSMTabBar/PSMOverflowPopUpButton.m delete mode 100644 Frameworks/PSMTabBar/PSMProgressIndicator.h delete mode 100644 Frameworks/PSMTabBar/PSMProgressIndicator.m delete mode 100644 Frameworks/PSMTabBar/PSMRolloverButton.h delete mode 100644 Frameworks/PSMTabBar/PSMRolloverButton.m delete mode 100644 Frameworks/PSMTabBar/PSMTabBarCell.h delete mode 100644 Frameworks/PSMTabBar/PSMTabBarCell.m delete mode 100644 Frameworks/PSMTabBar/PSMTabBarControl.h delete mode 100644 Frameworks/PSMTabBar/PSMTabBarControl.m delete mode 100644 Frameworks/PSMTabBar/PSMTabBarController.h delete mode 100644 Frameworks/PSMTabBar/PSMTabBarController.m delete mode 100644 Frameworks/PSMTabBar/PSMTabDragAssistant.h delete mode 100644 Frameworks/PSMTabBar/PSMTabDragAssistant.m delete mode 100644 Frameworks/PSMTabBar/PSMTabDragView.h delete mode 100644 Frameworks/PSMTabBar/PSMTabDragView.m delete mode 100644 Frameworks/PSMTabBar/PSMTabDragWindow.h delete mode 100644 Frameworks/PSMTabBar/PSMTabDragWindow.m delete mode 100644 Frameworks/PSMTabBar/PSMTabDragWindowController.h delete mode 100644 Frameworks/PSMTabBar/PSMTabDragWindowController.m delete mode 100644 Frameworks/PSMTabBar/PSMTabStyle.h delete mode 100644 Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h delete mode 100644 Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m diff --git a/Frameworks/PSMTabBar/Images/AddTabButton.png b/Frameworks/PSMTabBar/Images/AddTabButton.png deleted file mode 100644 index ee76231202cddd0afdd0444817c1308f124c1d8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^Vn8g;!3HGxU+kX;q!^2X+?^QKos)S9?8-Ex^E#eS<^Cd(XvZKqDDEUHx3vIVCg!07zUa3IG5A diff --git a/Frameworks/PSMTabBar/Images/AddTabButtonPushed.png b/Frameworks/PSMTabBar/Images/AddTabButtonPushed.png deleted file mode 100644 index 633d0d51bf2d49ae432c942b83df8fc0fababcce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEa{HEjtmSN`?>!lvI6+sH*ppkausbtK%V*2u*1=Pmi M>FVdQ&MBb@0PUI|Y5)KL diff --git a/Frameworks/PSMTabBar/Images/AddTabButtonRollover.png b/Frameworks/PSMTabBar/Images/AddTabButtonRollover.png deleted file mode 100644 index 633d0d51bf2d49ae432c942b83df8fc0fababcce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEa{HEjtmSN`?>!lvI6+sH*ppkausbtK%V*2u*1=Pmi M>FVdQ&MBb@0PUI|Y5)KL diff --git a/Frameworks/PSMTabBar/Images/AdiumGradient.png b/Frameworks/PSMTabBar/Images/AdiumGradient.png deleted file mode 100644 index bad81b86b2a0964a186fda423522601488feae0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^0YEIq$P6TN?{&@xQp^E9A+8@jeAvA|b~TX8#%Zvqb*TV&o!)4h{CzUoc6xZUnzo)7 zNuK2M!c?otB(l5P-O1^8H=0Dm8>>zhqjEv{J8tqfAQ>)QAyo8tN zY;>KXc9|J`Qf6u+|26zpW%e4%2UJz~SQoq1adj+qkF`Qo-#?MBhWd&XtFMN9fPWsx Vrn%i8LBs$6002ovPDHLkV1mp;bua(` diff --git a/Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Pressed.png b/Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Pressed.png deleted file mode 100644 index 01570fbdbb7c6f932aff717205a4c4998a72882f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 271 zcmV+q0r38bP)Y_ZOIr+xk>{7*RT(^)TD%%B8TZBT8uC*%wQ+U+r@ z2I?~Og9;xDIRJ#mAX0{Y4BmYZb^R~4{onS#{{@8S-N)d&6~Y7wgCKAe~7^?>|4#hyP{&Cm&qcvOVco(y^B92N(WN{x1s+lmGnxE&j*+F9pIFAPc0L0RTXF Vov{buakKyc002ovPDHLkV1j8Ta~c2u diff --git a/Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Rollover.png b/Frameworks/PSMTabBar/Images/AquaTabCloseDirty_Front_Rollover.png deleted file mode 100644 index 55db65313c5c7df8e37bceb1cb7820294de29818..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 276 zcmV+v0qg#WP){QlfKD91LYn6H;eBv-%7ug0!a(7 aY6bwgil+NzTNuv(00006um!Su()Kk*i_@%07*qoM6N<$f@N2Ds{jB1 diff --git a/Frameworks/PSMTabBar/Images/AquaTabClose_Front_Pressed.png b/Frameworks/PSMTabBar/Images/AquaTabClose_Front_Pressed.png deleted file mode 100644 index 8050f582de17e1bd0397dbc72cc999fe568d780f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmV++0p9+JP)wV6i#^TAUlj5ljUB0L6{bY1emr zI_@dw_IR%2n32v+Se0f=xg(0J-osztcQ8g*JOORhug`0@#-wGI&Vh_gCiRlJaOUgf9#ZTVb2_qY7S nE7pI1!YYs1=Z%0b7`EvH5Kp1G#FT_M00000NkvXXu0mjfxw3y< diff --git a/Frameworks/PSMTabBar/Images/AquaTabClose_Front_Rollover.png b/Frameworks/PSMTabBar/Images/AquaTabClose_Front_Rollover.png deleted file mode 100644 index 3612b28e6f1ca3b2f132789a631dc6b80297107c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 296 zcmV+@0oVSCP)3)>NXpNHA+Zf4u)3GIh2b6l-W-q=0(NZJoAZtz=*4fcSCdxGYu{9Kpy)vRrj_%q uCVi8I2Fg4BZx-KUzLkC}1(FtE)eHcV=&XzKEPC$%0000My}kfQwFmfwxaQ^My?y)E&(AL|E-o`O z^Z)<<#>U2xk&!?W8CY3a0i}Qds1m{ek|ri5!NI{%QBf;buJrNo@%8ncF=GZ$eDdVU zK=RO`Lq$bJn>K9%vP(-#j~+d0X=!O=V*}(ufSa3}r>7@`y->D75$Gh{k|4j}u4io> zoeUN2ahCj1vNcNLxsrzZl`ifo=^0is=JLkD8ls`5iAnqlnklJT0-H?c76UcrdAc}; zRK)rAy7C=%5IJh|L7n;Gl$k&OJ%6p#dujXTFDc4G&E@CXHJYAyN@w@_?Gy-R^KzV~ zcLrtV~^MTI=icWMuB90__DMy}kfQ^#=HaxaQ^MEnd9X&(AL|E-o`O z^Z)<<#>U2xk&!?W834tBz{<)Bs1nFnxpJkAjg6v9XeE0RJ3W+CLp`CwDjoFqb4RMmX?-q1we+In;SA$se3WVmHH(?e!)ks?LT;! zVfBHwK(Pib1I3NA+>CoBB&PaJni8ZTr{hs(sa)y3x=U2g%Bk1cT1D(jtz$A!Yrdz8 zV@O4uZ?7xgVF!_;HXqcP4;mR?{@Z`uRcdK|`pc7UDs1oP@CUM-oNRVYYHpF@GM*_- zI<8I2SW6Df=Ic2g`E_>b|AI$%?zi<+A8a|eIJm#;&GOA=R`EKKYt3)(TJ`GiMva|Q iuHW99IdA==zdxDeGFTT2+dT(`GlQqApUXO@geCy!w6Bi< diff --git a/Frameworks/PSMTabBar/Images/AquaTabNewRollover.png b/Frameworks/PSMTabBar/Images/AquaTabNewRollover.png deleted file mode 100644 index 4d469f8a65fae2136be6b7ab24e87ae449023998..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)Gmu>My}kfQ^#=HaxaQ^M{rK_2&(AL|E-o`O z^Z)<<#>U2xk&!?W834tBz{<)Bs1nFnxpJkAjg6v9XeE0RJ3W+CLp`CwDjoFqb4RMmX?-q1we+In;SCsvBeL6pu_Y_g8YJy{Mmo- zFvIEtZGmD9S_X<6XSo^oOh`=in=~azLr%w|%u>11dv%wno|RLtv$cxYuC51VK&|a&ofSHL1BpipzMW zH0iiDEn_V?Fq^OEc;wgFrT+^a-MQb^Q+=@I;Nsx^vNy{&n_0!{M6NZzy=&F0!y7er jPPu-2Z|1!9kN*B-lFMLSENu526wVBuu6{1-oD!MP)t-s@bK{Q z@$vHV^6c#F?(XjG?d|I7>gVU@`T6FMd~>+Agd z{QLX+_V)Jr`ug?t^_G^H^YioYsNTW=0078IL_t(|+TGU45`!QR1klD6f-#Fh^Z#F( zD$b2HP7p2MxuF>j6j&|-Q;?b@f376EI1zewMB6;4R^KRBJ$p?7EO-^9ouP q?`T>_LfQRUfxFyIDRTvf^h- diff --git a/Frameworks/PSMTabBar/Images/AquaTabsDown.png b/Frameworks/PSMTabBar/Images/AquaTabsDown.png deleted file mode 100644 index 65f3ccb98bb92ed953c9a4cce0fe5210e7ae137f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz0!3-q7&-XC_QceLrA+8fA&baaL`@SphH=KPt z`_QY&dtdeKe%-g{^@M$I^Vfb%U-va<KL;41Wyw^)UM*(FSJYD@<);T3K F0RSDsM%(}Z diff --git a/Frameworks/PSMTabBar/Images/AquaTabsDownGraphite.png b/Frameworks/PSMTabBar/Images/AquaTabsDownGraphite.png deleted file mode 100644 index 15bcc19c75c1ee58c3f9d94b16109b61ea2c3a79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmVFe6v;Mn5s=IHC^@&CKU(4?)osh=HJ|mFX=@XF)g-{Be&_#a|vzJ_ZGcykFP=0000?A+Dc3eR}-(@ztwWpFMl_ z=FOXF(`Gz*^5n&f7au=ax>8SF1 RUx4}z= diff --git a/Frameworks/PSMTabBar/Images/AquaTabsSeparator.png b/Frameworks/PSMTabBar/Images/AquaTabsSeparator.png deleted file mode 100644 index 60f38a2154bf04603bbca28d3f9ec484794aa1ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{L!2%>#pSM#4Qih%`jv*Y;$+LdW^=xi_$rd<^uYduo5OGn6rM?3eUb>jG+K@O1TaS?83{ F1OS@|A4UKG diff --git a/Frameworks/PSMTabBar/Images/AquaTabsSeparatorDown.png b/Frameworks/PSMTabBar/Images/AquaTabsSeparatorDown.png deleted file mode 100644 index 5f40dfc2119b7a57d836cb2162a841d54f6505e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{L!3-qLB-myEDW?FR5Z7tbX6!otZ1&Fk?dxu3 z%(;?0^IFK1%MsJA$Iia5-f&B~`H4=)bIVB|JQjV5So6R(pYo4k44ofy`glX(f`6nnZjhG>W; zCrFeu2;Ow%<>k%Uo_9AZDJ7+cx%2=3|Me4R&5Du@_#^HkYuv-QXz7wAQH>#%0-v2W zp1r+2|E6C2zCG+G*qPNNm|YJ098+&w#2BflXV%3wVfIDQMcoTC7%Bx;EEImR<+%b+ hlJn6EXC*JyFdW>YP&!Z3Y9i2j22WQ%mvv4FO#ny(Kr8?N diff --git a/Frameworks/PSMTabBar/Images/SequelProTabDirty@2x.png b/Frameworks/PSMTabBar/Images/SequelProTabDirty@2x.png deleted file mode 100644 index c06b5955507653d6b8eeba92aab041080f0a799e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307 zcmV-30nGl1P)Px#?MXyIR7ef&lrav%FbqYLa0*6dZc%ZIW-F|msNIq|7eGA%OU2d|af=2Uk*E^+ zO{I>cODy~QxptijQJyk^trL(rfcIW%tgVh(=-`M zt^lA{N@*(e0&$^GfZsd==hTWdtVNt13XJ1;q1YA0Xa0k8?l}y@eddcM?0^(aROJn* zg$2R~&9jAA(!v63z-u(Hz;_kbFv8j`+{u<-Mc|aPOyHj<@CFZTQP+aBeuV%4002ovPDHLk FV1lZ)gHQkf diff --git a/Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed.png b/Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed.png deleted file mode 100644 index d0befe1203ede3748ecf872234af0f80dde6fe7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6T7>k44ofy`glX(f`%<*(_4ABtn z4LZnsSb=BD+I1Jzl@-EXs7S85tnl&4(b?(W8Xm1uQ}bf}moWGJxotdc0&z>Hl&}5D zY2MgjEttE-DNWuiMeppK(%@%yCKqHBj&WE%*U#x;%+}o!Xq78qV7c^4_ay7*R%IU2 zD(CiAHS#j~{+Z6tH1DTOdd`hT@h1~5rex+e-TS?&G19N*prq%k{n?kdDNS0h_~_|( Z=G;Aw;@lq!E&|=j;OXk;vd$@?2>|?kS5N=| diff --git a/Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed@2x.png b/Frameworks/PSMTabBar/Images/SequelProTabDirty_Pressed@2x.png deleted file mode 100644 index 06d74af23049c851454211e7ffbd26891a87b713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415 zcmV;Q0bu@#P)Px$SxH1eR7efYRy%HlFc7uPr=UYg#RU-6_J|_Op^`f!=SYqL6r3OpqM!@~+K7${ zMEs&e8?DyEup6X(5|Uxwyf+?fuoN0)Sq9TIJ?r6qp63A1E`^k`)w#K4S&vDQv=ZXu zIKJzLcbAG9@(#9b@070mWdm_|-lHo@4<2y05%%iZo>PTE8#CAxHb=dxDpA+9===Vg z?)$z7!%##~w3tpB48tI@EE8>um3Ktfbplt@G$Kt?;d$OMcrqeebWZ$lK8(SkU^GBm zPAfkr1P-_+7!A;KE-0?i;P-`cOen6=fFsP|7!9x#xuCd41FUl{D6Y`}namF^6U4xwAd8}yDFR~Gd@5K5O9fDIvPD!PH>Q66p+)Fa15Oqyj^hv4b$5C?Z~xIQXz1$|Ckh-}Sf$)F=?iKue62x@(#HS*002ov JPDHLkV1l4zurUAt diff --git a/Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover.png b/Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover.png deleted file mode 100644 index d0befe1203ede3748ecf872234af0f80dde6fe7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6T7>k44ofy`glX(f`%<*(_4ABtn z4LZnsSb=BD+I1Jzl@-EXs7S85tnl&4(b?(W8Xm1uQ}bf}moWGJxotdc0&z>Hl&}5D zY2MgjEttE-DNWuiMeppK(%@%yCKqHBj&WE%*U#x;%+}o!Xq78qV7c^4_ay7*R%IU2 zD(CiAHS#j~{+Z6tH1DTOdd`hT@h1~5rex+e-TS?&G19N*prq%k{n?kdDNS0h_~_|( Z=G;Aw;@lq!E&|=j;OXk;vd$@?2>|?kS5N=| diff --git a/Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover@2x.png b/Frameworks/PSMTabBar/Images/SequelProTabDirty_Rollover@2x.png deleted file mode 100644 index 06d74af23049c851454211e7ffbd26891a87b713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415 zcmV;Q0bu@#P)Px$SxH1eR7efYRy%HlFc7uPr=UYg#RU-6_J|_Op^`f!=SYqL6r3OpqM!@~+K7${ zMEs&e8?DyEup6X(5|Uxwyf+?fuoN0)Sq9TIJ?r6qp63A1E`^k`)w#K4S&vDQv=ZXu zIKJzLcbAG9@(#9b@070mWdm_|-lHo@4<2y05%%iZo>PTE8#CAxHb=dxDpA+9===Vg z?)$z7!%##~w3tpB48tI@EE8>um3Ktfbplt@G$Kt?;d$OMcrqeebWZ$lK8(SkU^GBm zPAfkr1P-_+7!A;KE-0?i;P-`cOen6=fFsP|7!9x#xuCd41FUl{D6Y`}namF^6U4xwAd8}yDFR~Gd@5K5O9fDIvPD!PH>Q66p+)Fa15Oqyj^hv4b$5C?Z~xIQXz1$|Ckh-}Sf$)F=?iKue62x@(#HS*002ov JPDHLkV1l4zurUAt diff --git a/Frameworks/PSMTabBar/Images/TabClose_Dirty.png b/Frameworks/PSMTabBar/Images/TabClose_Dirty.png deleted file mode 100644 index 5899b7372aecd2dbe1fcdc8fb97ddab7d4c8da51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmV+h0r~!kP)PBfAO&CoaC=$nc;4SURfI#Kp(b|MLTV z_+R#Z!scncOUl-lt?ym3dD{Ji|FY09`Op8~;(yHlQXq^0vOuaC01n-n*7(Z?82|tP M07*qoM6N<$f}y!^CIA2c diff --git a/Frameworks/PSMTabBar/Images/TabClose_Dirty_Pressed.png b/Frameworks/PSMTabBar/Images/TabClose_Dirty_Pressed.png deleted file mode 100644 index eb286a01e250e57ec56361269b61f9e79279378c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmV|4#hyP_SCr@3N zw%z-f_p!9?Qx{%N{x1s+lmGnxE&j*+F9pIFAPc0L0RV?lk}>WayH)@I002ovPDHLk FV1mwAXY2p~ diff --git a/Frameworks/PSMTabBar/Images/TabClose_Dirty_Rollover.png b/Frameworks/PSMTabBar/Images/TabClose_Dirty_Rollover.png deleted file mode 100644 index 599d47535b999a32a0b1cc8876a2f851a1e7c22a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255 zcmV2pi zHA6=;)YLPU7cDP3o`LW>ni&qe6m39vRndmSE)4(qx8Zp-^PeB+!~e2ZljhDV z*c5so^gzL;x$~|j{g;J?$$$R;7XM@ZmjYo7kOflB001nmnROs!7Nh_G002ovPDHLk FV1n7{VyXZD diff --git a/Frameworks/PSMTabBar/Images/TabClose_Front.png b/Frameworks/PSMTabBar/Images/TabClose_Front.png deleted file mode 100644 index 192b69910dc2cbc694b1ff262b9e466753269874..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 288 zcmV+*0pI?KP)jJKerM^%lt{-{gyA>h*Q%ezqs35xe3KBc7P@YB+{n zaoWI4n~D()$F$tR2wFt2gBE(Zqjdygmxy57CGE(dPb~097KQk*~4K?zL0y*l?YGQLvbihR}nr} m-246sYdm6$_Y#(5*rqq^VxHNo<;U9q0000%tdz7nz zx>Wo?!ae`cX_`-p9O;rEQ2*mISSpmwM800000NkvXXu0mjfXUl)F diff --git a/Frameworks/PSMTabBar/Images/TabClose_Front_Rollover.png b/Frameworks/PSMTabBar/Images/TabClose_Front_Rollover.png deleted file mode 100644 index ce45746e165cca81e665142b5eaae3f450dcd9c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR|LP)i971Ui1nDJmYYIfef|`uL$)%x32*Q{6y2o4i zo#p&|_i*ne!VG9i9&H6Y!3LctW;FD*gK?hSXLsYQ9fm%Qy6thKmu}rdFUOHMr8%&f zuWy*wH!~v5Av1wdw1{9AEwq`Cm35>+1lw$&t&HY3*<5}Qlpm?)H}a4F?xK~2(EgEj zF^DXYh0wd09(I_Edpu>g+2~KV4)cditXu*_J;MAFup(Z_>T9)6*QZ6bsMe=_`dYF2 l`x91p!b{!=ECs_heF5YOpix^lLn#0N002ovPDHLkV1fh(edz!I diff --git a/Frameworks/PSMTabBar/Images/TabNewMetal.png b/Frameworks/PSMTabBar/Images/TabNewMetal.png deleted file mode 100644 index be02d7083dcb5a48581153ba1bdfd3ee324a8546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)Gmu>My}kfQ^#=HaxaQ^Moj7sA&(AL|E-o`O z^Z)<<#>U2xk&!?W834tBz{<)Bs1nF9F)^{RvGMfu3=R&Cii(;%d9sg>kFT%qj2Sb) z3PHr7Lx+lriZ*T91Z0<%mL5HN6v(i&v;@h4!OE2@-Q3(@JP@7q=Yl=ZVfrOOe!+Vm z?%1`5Vd>6Bf6*EZ2ZdErotL(E$0qvp_W7&JYPl7eE0uWawTkFi7=o3fucR{DCYdC!1Z9np>o} zjAu%dj%(90){+CW`Ff5=ew|(V-{8TW`)xhd2U~tG4(=~|vwX9eRlH8*TJzhxR=qm> mF{DUy{q{wfUC&?t{mCS|nsxC*6;`0l3=E#GelF{r5}E*AhOcb^ diff --git a/Frameworks/PSMTabBar/Images/TabNewMetalPressed.png b/Frameworks/PSMTabBar/Images/TabNewMetalPressed.png deleted file mode 100644 index 18118ec363990dedfd2634e35431493173d0c1a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)Gmu>My}kfQ^#=HaxaQ^MO`0^x&(AL|E-o`O z^Z)<<#>U2xk&!?W834tBz{<)Bs1nF9F)^{RvGMfu3=R&Cii(;%d9sg>kFT%qj2Sb) z3PHr7Lx+lriZ*T91Z0<%mL5HN6v(i&v;@h4!OE2@-Q3(@JP>`RrRFryVfrOOe!qo>a~gb%EqDH&YFD@7KVqx67YFy3y;;85%qm_da;^F8U8`Ol n{uolExqkbi%&zCJ|Ndl>UCp}qp$aR|W(EdNS3j3^P6z}e? diff --git a/Frameworks/PSMTabBar/Images/TabNewMetalRollover.png b/Frameworks/PSMTabBar/Images/TabNewMetalRollover.png deleted file mode 100644 index 208c9640885a3f0d53731fca2da21e36c116ada2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)Gmu>My}kfQO$hJ_am~xi`~LmApPyf5W@cPm z-2eaojgdfPWF&+K6bGuYva$j)f`fyjqN3c~+$=3EZES3SB9kXi_VMxY_4S=GV+N25 z0f!D9Dk>`S^z_`cX;W!w>CvM{f#N16CNOyry>jJBWG;{$QJQ)J=r)6rAivWP_4 z`BW2M1GWVYJ&6nqEt0KGT8s<~dp>Ux^>CJ|W@NZxXOk4mU~%8KI3{Rv_Ei0^>a~~G g&#$~RbNMUz*+EM8Uv+wY2U^SE>FVdQ&MBb@0EoSWi{HS7${GLD!j)uXD|_)=1Fn%~N^pKj-TI%1NbBa&*+I%m$gbNlw$ h*-e_nA(mCa%%GVX7QS}1s4&p=44$rjF6*2UngB6(RF(h$ diff --git a/Frameworks/PSMTabBar/Images/overflowImagePressed.png b/Frameworks/PSMTabBar/Images/overflowImagePressed.png deleted file mode 100644 index f69168375a55e05338615f757c89045f3dbdaa22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W=!2%@ZVz%W1sWqN1jv*44lYg9NXyOs#32(e2 z-^QXMrq!U4lD?hq!G7ML1CyAN7izZ7I&t7w+EdL6*+nA9oC3LmPaHUKD(j_IjpULB zOUYwSL0thrkwZz3&i|SG(Ef3`n4|>vi!`5Bo<%<5lK+hVnypNq+_v$?O+!&HgE(eS zsqG!F4n;hAG$YL0_+E>aal=Lx6$4x4;}!BR7VUS-U3APqtjlPIlb>IDdVIXRyr(A% cx9J|n9?O)IjZNy?f$nDTboFyt=akR{0NR*V9{>OV diff --git a/Frameworks/PSMTabBar/Images/pi.png b/Frameworks/PSMTabBar/Images/pi.png deleted file mode 100644 index 9cd57539b533805dcc10968be2bf3460c3f00f3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbMf^8lX^S0MfW|9>Dk%zUT0+G;AWEL660Z!ma}klj#rWiiPjU*6gRWWloDd*<5yMmoYlrQy(%?NusTb9 zW`TF|=6rbp7Zvkv<@9o6e}_IT0}Xvs32Q@kosKgqQ9y%NdAc};NJz3CWKLpnWMJ5E z=2cGg*4*g-_5Q+&Edov)U_znu?VCxAH|#$Yr9`o9C=0uJ?SJ_vqsG@CN4CgZmzo0 zF3IwDRXSCFkH@quv7KXkefH_=+cQ4MIWN1USyLnC9 - -@interface NSBezierPath (AMShading) - -- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; -- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; - -- (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor; -- (void)linearVerticalGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor; - -- (void)bilinearGradientFillWithOuterColor:(NSColor *)outerColor innerColor:(NSColor *)innerColor; - -@end diff --git a/Frameworks/PSMTabBar/NSBezierPath_AMShading.m b/Frameworks/PSMTabBar/NSBezierPath_AMShading.m deleted file mode 100755 index 034be0976..000000000 --- a/Frameworks/PSMTabBar/NSBezierPath_AMShading.m +++ /dev/null @@ -1,126 +0,0 @@ -// -// NSBezierPath_AMShading.m -// ------------------------ -// -// Created by Andreas on 2005-06-01. -// Copyright 2005 Andreas Mayer. All rights reserved. -// - -#import "NSBezierPath_AMShading.h" - -@implementation NSBezierPath (AMShading) - -static void linearShadedColor(void *info, const CGFloat *in, CGFloat *out) -{ - CGFloat *colors = (CGFloat *)info; - *out++ = colors[0] + *in * colors[8]; - *out++ = colors[1] + *in * colors[9]; - *out++ = colors[2] + *in * colors[10]; - *out++ = colors[3] + *in * colors[11]; -} - -static void bilinearShadedColor(void *info, const CGFloat *in, CGFloat *out) -{ - CGFloat *colors = (CGFloat *)info; - CGFloat factor = (*in)*2.0f; - if (*in > 0.5) { - factor = 2-factor; - } - *out++ = colors[0] + factor * colors[8]; - *out++ = colors[1] + factor * colors[9]; - *out++ = colors[2] + factor * colors[10]; - *out++ = colors[3] + factor * colors[11]; -} - -- (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor -{ - static const CGFunctionCallbacks callbacks = {0, &linearShadedColor, NULL}; - - [self customHorizontalFillWithCallbacks:callbacks firstColor:startColor secondColor:endColor]; -} - -- (void)linearVerticalGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor -{ - static const CGFunctionCallbacks callbacks = {0, &linearShadedColor, NULL}; - - [self customVerticalFillWithCallbacks:callbacks firstColor:startColor secondColor:endColor]; -} - -- (void)bilinearGradientFillWithOuterColor:(NSColor *)outerColor innerColor:(NSColor *)innerColor -{ - static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL}; - - [self customHorizontalFillWithCallbacks:callbacks firstColor:innerColor secondColor:outerColor]; -} - -- (void)customFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint -{ - CGColorSpaceRef colorspace; - CGShadingRef shading; - CGFunctionRef function; - CGFloat colors[12]; // pointer to color values - - // get my context - CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - - NSColor *deviceDependentFirstColor = [firstColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - NSColor *deviceDependentSecondColor = [secondColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - - // set up colors for gradient - colors[0] = [deviceDependentFirstColor redComponent]; - colors[1] = [deviceDependentFirstColor greenComponent]; - colors[2] = [deviceDependentFirstColor blueComponent]; - colors[3] = [deviceDependentFirstColor alphaComponent]; - - colors[4] = [deviceDependentSecondColor redComponent]; - colors[5] = [deviceDependentSecondColor greenComponent]; - colors[6] = [deviceDependentSecondColor blueComponent]; - colors[7] = [deviceDependentSecondColor alphaComponent]; - - // difference between start and end color for each color components - colors[8] = (colors[4]-colors[0]); - colors[9] = (colors[5]-colors[1]); - colors[10] = (colors[6]-colors[2]); - colors[11] = (colors[7]-colors[3]); - - // draw gradient - colorspace = CGColorSpaceCreateDeviceRGB(); - size_t components = 1 + CGColorSpaceGetNumberOfComponents(colorspace); - static const CGFloat domain[2] = {0.0f, 1.0f}; - static const CGFloat range[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; - //static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL}; - - // Create a CGFunctionRef that describes a function taking 1 input and kChannelsPerColor outputs. - function = CGFunctionCreate(colors, 1, domain, components, range, &functionCallbacks); - - shading = CGShadingCreateAxial(colorspace, startPoint, endPoint, function, NO, NO); - - CGContextSaveGState(currentContext); - [self addClip]; - CGContextDrawShading(currentContext, shading); - CGContextRestoreGState(currentContext); - - CGShadingRelease(shading); - CGFunctionRelease(function); - CGColorSpaceRelease(colorspace); -} - -- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor -{ - [self customFillWithCallbacks:functionCallbacks - firstColor:firstColor - secondColor:secondColor - startPoint:CGPointMake(0, NSMinY([self bounds])) - endPoint:CGPointMake(0, NSMaxY([self bounds]))]; -} - -- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor -{ - [self customFillWithCallbacks:functionCallbacks - firstColor:firstColor - secondColor:secondColor - startPoint:CGPointMake(NSMinX([self bounds]), 0) - endPoint:CGPointMake(NSMaxX([self bounds]), 0)]; -} - -@end diff --git a/Frameworks/PSMTabBar/NSString_AITruncation.h b/Frameworks/PSMTabBar/NSString_AITruncation.h deleted file mode 100644 index cbcbf2c7f..000000000 --- a/Frameworks/PSMTabBar/NSString_AITruncation.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// NSString_AITruncation.h -// PSMTabBarControl -// -// Created by Evan Schoenberg on 7/14/07. -// - -#import - -@interface NSString (AITruncation) -- (NSString *)stringWithEllipsisByTruncatingToLength:(NSUInteger)length; -@end diff --git a/Frameworks/PSMTabBar/NSString_AITruncation.m b/Frameworks/PSMTabBar/NSString_AITruncation.m deleted file mode 100644 index 1015f21c8..000000000 --- a/Frameworks/PSMTabBar/NSString_AITruncation.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// NSString_AITruncation.m -// PSMTabBarControl -// -// Created by Evan Schoenberg on 7/14/07. -// From Adium, which is licensed under the GPL. Used in PSMTabBarControl with permission. -// The contents of this remain licensed under the GPL. -// - -#import "NSString_AITruncation.h" - -@implementation NSString (AITruncation) - -+ (id)ellipsis -{ - return [NSString stringWithUTF8String:"\xE2\x80\xA6"]; -} - -- (NSString *)stringWithEllipsisByTruncatingToLength:(NSUInteger)length -{ - NSString *returnString; - - if (length < [self length]) { - //Truncate and append the ellipsis - returnString = [[self substringToIndex:length-1] stringByAppendingString:[NSString ellipsis]]; - } else { - //We don't need to truncate, so don't append an ellipsis - returnString = [self copy]; - } - - return returnString; -} - -@end diff --git a/Frameworks/PSMTabBar/NSTabViewItemExtension.swift b/Frameworks/PSMTabBar/NSTabViewItemExtension.swift deleted file mode 100644 index cdd1320dd..000000000 --- a/Frameworks/PSMTabBar/NSTabViewItemExtension.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// SPTabViewItem.swift -// Sequel Ace -// -// Created by Jakub Kašpar on 23.01.2021. -// Copyright © 2021 Sequel-Ace. All rights reserved. -// - -import Cocoa - -extension NSTabViewItem { - @objc var databaseDocument: SPDatabaseDocument? { - return identifier as? SPDatabaseDocument - } -} diff --git a/Frameworks/PSMTabBar/PSMOverflowPopUpButton.h b/Frameworks/PSMTabBar/PSMOverflowPopUpButton.h deleted file mode 100644 index 02f10a31c..000000000 --- a/Frameworks/PSMTabBar/PSMOverflowPopUpButton.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// PSMOverflowPopUpButton.h -// PSMTabBarControl -// -// Created by John Pannell on 11/4/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -#import - -@interface PSMOverflowPopUpButton : NSPopUpButton { - NSImage *_PSMTabBarOverflowPopUpImage; - NSImage *_PSMTabBarOverflowDownPopUpImage; - BOOL _down; - BOOL _animatingAlternateImage; - NSTimer *_animationTimer; - CGFloat _animationValue; -} - -//alternate image display -- (BOOL)animatingAlternateImage; -- (void)setAnimatingAlternateImage:(BOOL)flag; - -// Notifications -- (void)notificationReceived:(NSNotification *)notification; - -// Animations -- (void)animateStep:(NSTimer *)timer; - -// archiving -- (void)encodeWithCoder:(NSCoder *)aCoder; -- (instancetype)initWithCoder:(NSCoder *)aDecoder; -@end diff --git a/Frameworks/PSMTabBar/PSMOverflowPopUpButton.m b/Frameworks/PSMTabBar/PSMOverflowPopUpButton.m deleted file mode 100644 index eae6394b8..000000000 --- a/Frameworks/PSMTabBar/PSMOverflowPopUpButton.m +++ /dev/null @@ -1,148 +0,0 @@ -// -// PSMOverflowPopUpButton.m -// PSMTabBarControl -// -// Created by John Pannell on 11/4/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -#import "PSMOverflowPopUpButton.h" -#import "PSMTabBarControl.h" - -#define TIMER_INTERVAL 1.0 / 15.0 -#define ANIMATION_STEP 0.033f - -@implementation PSMOverflowPopUpButton - -- (instancetype)initWithFrame:(NSRect)frameRect pullsDown:(BOOL)flag -{ - if ((self = [super initWithFrame:frameRect pullsDown:YES])) { - [self setBezelStyle:NSRegularSquareBezelStyle]; - [self setBordered:NO]; - [self setTitle:@""]; - [self setPreferredEdge:NSMaxXEdge]; - _PSMTabBarOverflowPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImage"]]; - _PSMTabBarOverflowDownPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImagePressed"]]; - _animatingAlternateImage = NO; - } - return self; -} - -- (void)drawRect:(NSRect)rect -{ - if(_PSMTabBarOverflowPopUpImage == nil){ - [super drawRect:rect]; - return; - } - - NSImage *image = (_down) ? _PSMTabBarOverflowDownPopUpImage : _PSMTabBarOverflowPopUpImage; - NSSize imageSize = [image size]; - NSRect bounds = [self bounds]; - - NSPoint drawPoint = NSMakePoint(NSMidX(bounds) - (imageSize.width * 0.5f), NSMidY(bounds) - (imageSize.height * 0.5f)); - NSRect drawRect = NSMakeRect(drawPoint.x, drawPoint.y, imageSize.width, imageSize.height); - - [image drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:(_animatingAlternateImage ? 0.7f : 1.0f) respectFlipped:YES hints:nil]; - - if (_animatingAlternateImage) { - NSImage *alternateImage = [self alternateImage]; - NSSize altImageSize = [alternateImage size]; - drawPoint = NSMakePoint(NSMidX(bounds) - (altImageSize.width * 0.5f), NSMidY(bounds) - (altImageSize.height * 0.5f)); - drawRect = NSMakeRect(drawPoint.x, drawPoint.y, altImageSize.width, altImageSize.height); - - [[self alternateImage] drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:sinf(_animationValue * (float)M_PI) respectFlipped:YES hints:nil]; - } -} - -- (void)mouseDown:(NSEvent *)event -{ - _down = YES; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationReceived:) name:NSMenuDidEndTrackingNotification object:[self menu]]; - [self setNeedsDisplay:YES]; - [super mouseDown:event]; -} - -- (void)setHidden:(BOOL)value -{ - if ([self isHidden] != value) { - if (value) { - // Stop any animating alternate image if we hide - (void)([_animationTimer invalidate]), _animationTimer = nil; - } else if (_animatingAlternateImage) { - // Restart any animating alternate image if we unhide - _animationValue = ANIMATION_STEP; - _animationTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(animateStep:) userInfo:nil repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; - } - } - - [super setHidden:value]; -} - -- (void)notificationReceived:(NSNotification *)notification -{ - _down = NO; - [self setNeedsDisplay:YES]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)setAnimatingAlternateImage:(BOOL)flag -{ - if (_animatingAlternateImage != flag) { - _animatingAlternateImage = flag; - - if (![self isHidden]) { - if (flag) { - _animationValue = ANIMATION_STEP; - _animationTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(animateStep:) userInfo:nil repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; - - } else { - (void)([_animationTimer invalidate]), _animationTimer = nil; - } - - [self setNeedsDisplay:YES]; - } - } -} - -- (BOOL)animatingAlternateImage; -{ - return _animatingAlternateImage; -} - -- (void)animateStep:(NSTimer *)timer -{ - _animationValue += ANIMATION_STEP; - - if (_animationValue >= 1) { - _animationValue = ANIMATION_STEP; - } - - [self setNeedsDisplay:YES]; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_PSMTabBarOverflowPopUpImage forKey:@"PSMTabBarOverflowPopUpImage"]; - [aCoder encodeObject:_PSMTabBarOverflowDownPopUpImage forKey:@"PSMTabBarOverflowDownPopUpImage"]; - [aCoder encodeBool:_animatingAlternateImage forKey:@"PSMTabBarOverflowAnimatingAlternateImage"]; - } -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - if ( (self = [super initWithCoder:aDecoder]) ) { - if ([aDecoder allowsKeyedCoding]) { - _PSMTabBarOverflowPopUpImage = [aDecoder decodeObjectForKey:@"PSMTabBarOverflowPopUpImage"]; - _PSMTabBarOverflowDownPopUpImage = [aDecoder decodeObjectForKey:@"PSMTabBarOverflowDownPopUpImage"]; - [self setAnimatingAlternateImage:[aDecoder decodeBoolForKey:@"PSMTabBarOverflowAnimatingAlternateImage"]]; - } - } - return self; -} - -@end diff --git a/Frameworks/PSMTabBar/PSMProgressIndicator.h b/Frameworks/PSMTabBar/PSMProgressIndicator.h deleted file mode 100644 index f72c1be96..000000000 --- a/Frameworks/PSMTabBar/PSMProgressIndicator.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// PSMProgressIndicator.h -// PSMTabBarControl -// -// Created by John Pannell on 2/23/06. -// Copyright 2006 Positive Spin Media. All rights reserved. -// - -#import -#import "PSMTabBarControl.h" - -@interface PSMProgressIndicator : NSProgressIndicator { -} - -@end - -@interface PSMTabBarControl (LayoutPlease) - -- (void)update; - -@end diff --git a/Frameworks/PSMTabBar/PSMProgressIndicator.m b/Frameworks/PSMTabBar/PSMProgressIndicator.m deleted file mode 100644 index f79852a26..000000000 --- a/Frameworks/PSMTabBar/PSMProgressIndicator.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// PSMProgressIndicator.m -// PSMTabBarControl -// -// Created by John Pannell on 2/23/06. -// Copyright 2006 Positive Spin Media. All rights reserved. -// - -#import "PSMProgressIndicator.h" - -@implementation PSMProgressIndicator - -// overrides to make tab bar control re-layout things if status changes -- (void)setHidden:(BOOL)flag -{ - [super setHidden:flag]; - [(PSMTabBarControl *)[self superview] update]; -} - -- (void)stopAnimation:(id)sender -{ - [NSObject cancelPreviousPerformRequestsWithTarget:self - selector:@selector(startAnimation:) - object:nil]; - [super stopAnimation:sender]; -} -@end diff --git a/Frameworks/PSMTabBar/PSMRolloverButton.h b/Frameworks/PSMTabBar/PSMRolloverButton.h deleted file mode 100644 index 8c8f02ca9..000000000 --- a/Frameworks/PSMTabBar/PSMRolloverButton.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// PSMOverflowPopUpButton.h -// NetScrape -// -// Created by John Pannell on 8/4/04. -// Copyright 2004 Positive Spin Media. All rights reserved. -// - -#import - -@interface PSMRolloverButton : NSButton -{ - NSImage *_rolloverImage; - NSImage *_usualImage; - NSTrackingRectTag _myTrackingRectTag; -} - -// the regular image -- (void)setUsualImage:(nullable NSImage *)newImage; -- (nullable NSImage *)usualImage; - -// the rollover image -- (void)setRolloverImage:(nullable NSImage *)newImage; -- (nullable NSImage *)rolloverImage; - -// tracking rect for mouse events -- (void)rolloverFrameDidChange:(nonnull NSNotification *)notification; -- (void)addTrackingRect; -- (void)removeTrackingRect; - -@end diff --git a/Frameworks/PSMTabBar/PSMRolloverButton.m b/Frameworks/PSMTabBar/PSMRolloverButton.m deleted file mode 100644 index fb81c0ddf..000000000 --- a/Frameworks/PSMTabBar/PSMRolloverButton.m +++ /dev/null @@ -1,173 +0,0 @@ -// -// PSMOverflowPopUpButton.m -// NetScrape -// -// Created by John Pannell on 8/4/04. -// Copyright 2004 Positive Spin Media. All rights reserved. -// - -#import "PSMRolloverButton.h" - -@implementation PSMRolloverButton - -- (void)awakeFromNib -{ - if ([[self superclass] instancesRespondToSelector:@selector(awakeFromNib)]) { - [super awakeFromNib]; - } - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(rolloverFrameDidChange:) - name:NSViewFrameDidChangeNotification - object:self]; - - [self setPostsFrameChangedNotifications:YES]; - [self resetCursorRects]; - - _myTrackingRectTag = -1; - _rolloverImage = nil; - _usualImage = nil; -} - -// the regular image -- (void)setUsualImage:(NSImage *)newImage -{ - _usualImage = newImage; - - [self setImage:_usualImage]; -} - -- (NSImage *)usualImage -{ - return _usualImage; -} - -- (void)setRolloverImage:(NSImage *)newImage -{ - _rolloverImage = newImage; -} - -- (NSImage *)rolloverImage -{ - return _rolloverImage; -} - -// Remove old tracking rects when we change superviews -- (void)viewWillMoveToSuperview:(NSView *)newSuperview -{ - [self removeTrackingRect]; - - [super viewWillMoveToSuperview:newSuperview]; -} - -- (void)viewDidMoveToSuperview -{ - [super viewDidMoveToSuperview]; - - [self resetCursorRects]; -} - -- (void)viewWillMoveToWindow:(NSWindow *)newWindow -{ - [self removeTrackingRect]; - - [super viewWillMoveToWindow:newWindow]; -} - -- (void)viewDidMoveToWindow -{ - [super viewDidMoveToWindow]; - - [self resetCursorRects]; -} - -- (void)rolloverFrameDidChange:(NSNotification *)notification -{ - [self resetCursorRects]; -} - -- (void)addTrackingRect -{ - // assign a tracking rect to watch for mouse enter/exit - NSPoint globalPoint; - - if (@available(macOS 10.12, *)) { - globalPoint = [[self window] convertPointToScreen:[NSEvent mouseLocation]]; - } else { - globalPoint = [[self window] convertRectToScreen:(CGRect){.origin=[NSEvent mouseLocation]}].origin; - } - - NSRect trackRect = [self bounds]; - NSPoint localPoint = [self convertPoint:globalPoint fromView:nil]; - - BOOL mouseInside = NSPointInRect(localPoint, trackRect); - - _myTrackingRectTag = [self addTrackingRect:trackRect owner:self userData:nil assumeInside:mouseInside]; -} - -- (void)removeTrackingRect -{ - if (_myTrackingRectTag != -1) { - [self removeTrackingRect:_myTrackingRectTag]; - } - - _myTrackingRectTag = -1; -} - -- (void)resetCursorRects -{ - // called when the button rect has been changed - [self removeTrackingRect]; - [self addTrackingRect]; -} - -- (void)setFrame:(NSRect)rect -{ - [super setFrame:rect]; - [self resetCursorRects]; -} - -- (void)setBounds:(NSRect)rect -{ - [super setBounds:rect]; - [self resetCursorRects]; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)coder -{ - [super encodeWithCoder:coder]; - - if ([coder allowsKeyedCoding]) { - [coder encodeObject:_rolloverImage forKey:@"rolloverImage"]; - [coder encodeObject:_usualImage forKey:@"usualImage"]; - [coder encodeInteger:_myTrackingRectTag forKey:@"myTrackingRectTag"]; - } -} - -- (instancetype)initWithCoder:(NSCoder *)decoder -{ - if ((self = [super initWithCoder:decoder])) { - if ([decoder allowsKeyedCoding]) { - _rolloverImage = [decoder decodeObjectForKey:@"rolloverImage"]; - _usualImage = [decoder decodeObjectForKey:@"usualImage"]; - _myTrackingRectTag = [decoder decodeIntegerForKey:@"myTrackingRectTag"]; - } - } - - return self; -} - -#pragma mark - - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [self removeTrackingRect]; - -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarCell.h b/Frameworks/PSMTabBar/PSMTabBarCell.h deleted file mode 100644 index 04c6e7976..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarCell.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// PSMTabBarCell.h -// PSMTabBarControl -// -// Created by John Pannell on 10/13/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -#import -#import "PSMTabBarControl.h" - -@class PSMTabBarControl; -@class PSMProgressIndicator; - -@interface PSMTabBarCell : NSActionCell { - // sizing - NSRect _frame; - NSSize _stringSize; - NSInteger _currentStep; - BOOL _isPlaceholder; - - // state - NSInteger _tabState; - NSTrackingRectTag _closeButtonTrackingTag; // left side tracking, if dragging - NSTrackingRectTag _cellTrackingTag; // right side tracking, if dragging - PSMProgressIndicator *_indicator; - BOOL _isInOverflowMenu; - BOOL _hasCloseButton; - BOOL _isCloseButtonSuppressed; - BOOL _hasIcon; - BOOL _hasLargeImage; - NSInteger _count; - NSColor *_countColor; - BOOL _isEdited; - NSColor *_backgroundColor; - id _customControlView; -} - -// creation/destruction -- (instancetype)initWithControlView:(PSMTabBarControl *)controlView; -- (instancetype)initPlaceholderWithFrame:(NSRect)frame expanded:(BOOL)value inControlView:(PSMTabBarControl *)controlView; - -// accessors -- (id)customControlView; -- (void)setCustomControlView:(id)view; -- (NSTrackingRectTag)closeButtonTrackingTag; -- (void)setCloseButtonTrackingTag:(NSTrackingRectTag)tag; -- (NSTrackingRectTag)cellTrackingTag; -- (void)setCellTrackingTag:(NSTrackingRectTag)tag; -- (CGFloat)width; -- (NSRect)frame; -- (void)setFrame:(NSRect)rect; -- (void)setStringValue:(NSString *)aString; -- (NSSize)stringSize; -- (NSAttributedString *)attributedStringValue; -- (NSInteger)tabState; -- (void)setTabState:(NSInteger)state; -- (NSProgressIndicator *)indicator; -- (BOOL)isInOverflowMenu; -- (void)setIsInOverflowMenu:(BOOL)value; -- (BOOL)hasCloseButton; -- (void)setHasCloseButton:(BOOL)set; -- (void)setCloseButtonSuppressed:(BOOL)suppress; -- (BOOL)isCloseButtonSuppressed; -- (BOOL)hasIcon; -- (void)setHasIcon:(BOOL)value; -- (BOOL)hasLargeImage; -- (void)setHasLargeImage:(BOOL)value; -- (NSInteger)count; -- (void)setCount:(NSInteger)value; -- (NSColor *)countColor; -- (void)setCountColor:(NSColor *)value; -- (BOOL)isPlaceholder; -- (void)setIsPlaceholder:(BOOL)value; -- (NSInteger)currentStep; -- (void)setCurrentStep:(NSInteger)value; -- (BOOL)isEdited; -- (void)setIsEdited:(BOOL)value; -- (void)setBackgroundColor:(NSColor *)aColor; -- (NSColor *)backgroundColor; - -// component attributes -- (NSRect)indicatorRectForFrame:(NSRect)cellFrame; -- (NSRect)closeButtonRectForFrame:(NSRect)cellFrame; -- (CGFloat)minimumWidthOfCell; -- (CGFloat)desiredWidthOfCell; - -// drawing -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; - -// tracking the mouse -- (void)mouseEntered:(NSEvent *)theEvent; -- (void)mouseExited:(NSEvent *)theEvent; - -// drag support -- (NSImage *)dragImage; - -// archiving -- (void)encodeWithCoder:(NSCoder *)aCoder; -- (instancetype)initWithCoder:(NSCoder *)aDecoder; - -@end - -@interface PSMTabBarControl (CellAccessors) - -- (id)style; - -@end - -@interface NSObject (IdentifierAccesors) - -- (NSImage *)largeImage; - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarCell.m b/Frameworks/PSMTabBar/PSMTabBarCell.m deleted file mode 100644 index 4792f6f7a..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarCell.m +++ /dev/null @@ -1,486 +0,0 @@ -// -// PSMTabBarCell.m -// PSMTabBarControl -// -// Created by John Pannell on 10/13/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -#import "PSMTabBarCell.h" -#import "PSMTabBarControl.h" -#import "PSMTabStyle.h" -#import "PSMProgressIndicator.h" -#import "PSMTabDragAssistant.h" - -@interface PSMTabBarControl (Private) -- (void)update; -@end - -@implementation PSMTabBarCell - -#pragma mark - -#pragma mark Creation/Destruction -- (instancetype)initWithControlView:(PSMTabBarControl *)controlView -{ - if ( (self = [super init]) ) { - _customControlView = controlView; - _closeButtonTrackingTag = 0; - _cellTrackingTag = 0; - _indicator = [[PSMProgressIndicator alloc] initWithFrame:NSMakeRect(0.0f,0.0f,kPSMTabBarIndicatorWidth,kPSMTabBarIndicatorWidth)]; - [_indicator setStyle:NSProgressIndicatorSpinningStyle]; - [_indicator setAutoresizingMask:NSViewMinYMargin]; - _hasCloseButton = YES; - _isCloseButtonSuppressed = NO; - _count = 0; - _countColor = nil; - _isEdited = NO; - _isPlaceholder = NO; - _backgroundColor = nil; - self.accessibilityRole = NSAccessibilityButtonRole; - self.accessibilityHelp = [self accessibilityHelpGenerated]; - self.accessibilityFocused = ([self tabState] == 2); - } - return self; -} - -- (instancetype)initPlaceholderWithFrame:(NSRect)frame expanded:(BOOL)value inControlView:(PSMTabBarControl *)controlView -{ - if ( (self = [super init]) ) { - _customControlView = controlView; - _isPlaceholder = YES; - if (!value) { - if ([controlView orientation] == PSMTabBarHorizontalOrientation) { - frame.size.width = 0.0f; - } else { - frame.size.height = 0.0f; - } - } - [self setFrame:frame]; - _closeButtonTrackingTag = 0; - _cellTrackingTag = 0; - _indicator = nil; - _hasCloseButton = YES; - _isCloseButtonSuppressed = NO; - _count = 0; - _countColor = nil; - _isEdited = NO; - _backgroundColor = nil; - - if (value) { - [self setCurrentStep:(kPSMTabDragAnimationSteps - 1)]; - } else { - [self setCurrentStep:0]; - } - } - return self; -} - -- (void)dealloc -{ - [_indicator removeFromSuperviewWithoutNeedingDisplay]; -} - -#pragma mark - -#pragma mark Accessors - -- (id)customControlView -{ - return _customControlView; -} - -- (void)setCustomControlView:(id)view -{ - // no retain release pattern, as this simply switches a tab to another view. - _customControlView = view; -} - -- (NSTrackingRectTag)closeButtonTrackingTag -{ - return _closeButtonTrackingTag; -} - -- (void)setCloseButtonTrackingTag:(NSTrackingRectTag)tag -{ - _closeButtonTrackingTag = tag; -} - -- (NSTrackingRectTag)cellTrackingTag -{ - return _cellTrackingTag; -} - -- (void)setCellTrackingTag:(NSTrackingRectTag)tag -{ - _cellTrackingTag = tag; -} - -- (CGFloat)width -{ - return _frame.size.width; -} - -- (NSRect)frame -{ - return _frame; -} - -- (void)setFrame:(NSRect)rect -{ - _frame = rect; - - //move the status indicator along with the rest of the cell - if (![[self indicator] isHidden]) { - [[self indicator] setFrame:[self indicatorRectForFrame:rect]]; - } -} - -- (void)setStringValue:(NSString *)aString -{ - [super setStringValue:aString]; - _stringSize = [[self attributedStringValue] size]; - // need to redisplay now - binding observation was too quick. - [_customControlView update]; -} - -- (NSSize)stringSize -{ - return _stringSize; -} - -- (NSAttributedString *)attributedStringValue -{ - return [[(PSMTabBarControl *)_customControlView style] attributedStringValueForTabCell:self]; -} - -- (NSInteger)tabState -{ - return _tabState; -} - -- (void)setTabState:(NSInteger)state -{ - _tabState = state; -} - -- (NSProgressIndicator *)indicator -{ - return _indicator; -} - -- (BOOL)isInOverflowMenu -{ - return _isInOverflowMenu; -} - -- (void)setIsInOverflowMenu:(BOOL)value -{ - if (_isInOverflowMenu != value) { - _isInOverflowMenu = value; - if ([[[self customControlView] delegate] respondsToSelector:@selector(tabView:tabViewItem:isInOverflowMenu:)]) { - [[[self customControlView] delegate] tabView:[self customControlView] tabViewItem:[self representedObject] isInOverflowMenu:_isInOverflowMenu]; - } - } -} - -- (BOOL)hasCloseButton -{ - return _hasCloseButton; -} - -- (void)setHasCloseButton:(BOOL)set; -{ - _hasCloseButton = set; -} - -- (void)setCloseButtonSuppressed:(BOOL)suppress; -{ - _isCloseButtonSuppressed = suppress; -} - -- (BOOL)isCloseButtonSuppressed; -{ - return _isCloseButtonSuppressed; -} - -- (BOOL)hasIcon -{ - return _hasIcon; -} - -- (void)setHasIcon:(BOOL)value -{ - _hasIcon = value; -} - -- (BOOL)hasLargeImage -{ - return _hasLargeImage; -} - -- (void)setHasLargeImage:(BOOL)value -{ - _hasLargeImage = value; -} - -- (NSInteger)count -{ - return _count; -} - -- (void)setCount:(NSInteger)value -{ - _count = value; -} - -- (NSColor *)countColor -{ - return _countColor; -} - -- (void)setCountColor:(NSColor *)color -{ - _countColor = color; -} - -- (BOOL)isPlaceholder -{ - return _isPlaceholder; -} - -- (void)setIsPlaceholder:(BOOL)value; -{ - _isPlaceholder = value; -} - -- (NSInteger)currentStep -{ - return _currentStep; -} - -- (void)setCurrentStep:(NSInteger)value -{ - if(value < 0) - value = 0; - - if(value > (kPSMTabDragAnimationSteps - 1)) - value = (kPSMTabDragAnimationSteps - 1); - - _currentStep = value; -} - -- (BOOL)isEdited -{ - return _isEdited; -} - -- (void)setIsEdited:(BOOL)value -{ - _isEdited = value; -} - -- (NSColor *)backgroundColor { - return _backgroundColor; -} - -- (void)setBackgroundColor:(NSColor *)aColor -{ - _backgroundColor = aColor; -} - -#pragma mark - -#pragma mark Bindings - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - // the progress indicator, label, icon, or count has changed - redraw the control view - //[_customControlView update]; - //I seem to have run into some odd issue with update not being called at the right time. This seems to avoid the problem. - [_customControlView performSelector:@selector(update) withObject:nil afterDelay:0.0]; -} - -#pragma mark - -#pragma mark Component Attributes - -- (NSRect)indicatorRectForFrame:(NSRect)cellFrame -{ - return [[(PSMTabBarControl *)_customControlView style] indicatorRectForTabCell:self]; -} - -- (NSRect)closeButtonRectForFrame:(NSRect)cellFrame -{ - return [[(PSMTabBarControl *)_customControlView style] closeButtonRectForTabCell:self withFrame:cellFrame]; -} - -- (CGFloat)minimumWidthOfCell -{ - return [[(PSMTabBarControl *)_customControlView style] minimumWidthOfTabCell:self]; -} - -- (CGFloat)desiredWidthOfCell -{ - return [[(PSMTabBarControl *)_customControlView style] desiredWidthOfTabCell:self]; -} - -#pragma mark - -#pragma mark Drawing - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - if (_isPlaceholder) { - if (![_customControlView usesSafariStyleDragging]) { - [[NSColor colorWithCalibratedWhite:0.0f alpha:0.2f] set]; - NSRectFillUsingOperation(cellFrame, NSCompositingOperationSourceAtop); - } - return; - } - - [[(PSMTabBarControl *)_customControlView style] drawTabCell:self]; -} - -#pragma mark - -#pragma mark Tracking - -- (void)mouseEntered:(NSEvent *)theEvent -{ - if ([theEvent trackingNumber] == _cellTrackingTag) { - [self setHighlighted:YES]; - [_customControlView setNeedsDisplay:NO]; - } - - // scrubtastic - if ([_customControlView allowsScrubbing] && ([theEvent modifierFlags] & NSEventModifierFlagOption)) - [_customControlView tabClick:self]; - - // tell the control we only need to redraw the affected tab - [_customControlView setNeedsDisplayInRect:NSInsetRect([self frame], -2, -2)]; -} - -- (void)mouseExited:(NSEvent *)theEvent -{ - - if ([theEvent trackingNumber] == _cellTrackingTag) { - [self setHighlighted:NO]; - [_customControlView setNeedsDisplay:NO]; - } - - //tell the control we only need to redraw the affected tab - [_customControlView setNeedsDisplayInRect:NSInsetRect([self frame], -2, -2)]; -} - -#pragma mark - -#pragma mark Drag Support - -- (NSImage *)dragImage -{ - NSRect cellFrame = [(id )[(PSMTabBarControl *)_customControlView style] dragRectForTabCell:self orientation:(PSMTabBarOrientation)[(PSMTabBarControl *)_customControlView orientation]]; - //NSRect cellFrame = [self frame]; - - // Determine the target coordinates to draw into - NSRect oldFrame = [self frame]; - NSRect tabDrawFrame = oldFrame; - tabDrawFrame.origin.x -= cellFrame.origin.x; - - // Draw the tab into a new image - NSImage *image = [[NSImage alloc] initWithSize:cellFrame.size]; - -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [image setFlipped:YES]; - [image lockFocus]; -#else - [image lockFocusFlipped:YES]; -#endif - [self setFrame:tabDrawFrame]; - - [(id )[(PSMTabBarControl *)_customControlView style] drawTabCellForDragImage:self]; - - [self setFrame:oldFrame]; - - [image unlockFocus]; - - // Add the indicator if appropriate - if (![[self indicator] isHidden]) { - NSImage *pieImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"pi"]]; - [image lockFocus]; - NSPoint indicatorPoint = NSMakePoint([self frame].size.width - MARGIN_X - kPSMTabBarIndicatorWidth, MARGIN_Y); - NSRect indicatorRect = NSMakeRect(indicatorPoint.x, indicatorPoint.y, [pieImage size].width, [pieImage size].height); - [pieImage drawInRect:indicatorRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0f respectFlipped:YES hints:nil]; - [image unlockFocus]; - } - - return image; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeRect:_frame forKey:@"frame"]; - [aCoder encodeSize:_stringSize forKey:@"stringSize"]; - [aCoder encodeBool:_isPlaceholder forKey:@"isPlaceholder"]; - [aCoder encodeInteger:_tabState forKey:@"tabState"]; - [aCoder encodeInteger:_closeButtonTrackingTag forKey:@"closeButtonTrackingTag"]; - [aCoder encodeInteger:_cellTrackingTag forKey:@"cellTrackingTag"]; - [aCoder encodeObject:_indicator forKey:@"indicator"]; - [aCoder encodeBool:_isInOverflowMenu forKey:@"isInOverflowMenu"]; - [aCoder encodeBool:_hasCloseButton forKey:@"hasCloseButton"]; - [aCoder encodeBool:_isCloseButtonSuppressed forKey:@"isCloseButtonSuppressed"]; - [aCoder encodeBool:_hasIcon forKey:@"hasIcon"]; - [aCoder encodeBool:_hasLargeImage forKey:@"hasLargeImage"]; - [aCoder encodeInteger:_count forKey:@"count"]; - [aCoder encodeBool:_isEdited forKey:@"isEdited"]; - } -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if (self) { - if ([aDecoder allowsKeyedCoding]) { - _frame = [aDecoder decodeRectForKey:@"frame"]; - _stringSize = [aDecoder decodeSizeForKey:@"stringSize"]; - _isPlaceholder = [aDecoder decodeBoolForKey:@"isPlaceholder"]; - _tabState = [aDecoder decodeIntegerForKey:@"tabState"]; - _closeButtonTrackingTag = [aDecoder decodeIntegerForKey:@"closeButtonTrackingTag"]; - _cellTrackingTag = [aDecoder decodeIntegerForKey:@"cellTrackingTag"]; - _indicator = [aDecoder decodeObjectForKey:@"indicator"]; - _isInOverflowMenu = [aDecoder decodeBoolForKey:@"isInOverflowMenu"]; - _hasCloseButton = [aDecoder decodeBoolForKey:@"hasCloseButton"]; - _isCloseButtonSuppressed = [aDecoder decodeBoolForKey:@"isCloseButtonSuppressed"]; - _hasIcon = [aDecoder decodeBoolForKey:@"hasIcon"]; - _hasLargeImage = [aDecoder decodeBoolForKey:@"hasLargeImage"]; - _count = [aDecoder decodeIntegerForKey:@"count"]; - _isEdited = [aDecoder decodeBoolForKey:@"isEdited"]; - } - } - return self; -} - -#pragma mark - -#pragma mark Accessibility - -- (BOOL)accessibilityPerformPress { - [_customControlView tabClick:self]; - return YES; -} - -- (NSString *)accessibilityHelpGenerated { - if ([[[self customControlView] delegate] respondsToSelector:@selector(accessibilityStringForTabView:objectCount:)]) { - return [NSString stringWithFormat:@"%@, %lu %@", - [self stringValue], - (unsigned long)[self count], - [[[self customControlView] delegate] accessibilityStringForTabView:[[self customControlView] tabView] objectCount:[self count]]]; - } else { - return [self stringValue]; - } -} - -- (id)accessibilityHitTest:(NSPoint)point { - return NSAccessibilityUnignoredAncestor(self); -} - -- (id)accessibilityFocusedUIElement:(NSPoint)point { - return NSAccessibilityUnignoredAncestor(self); -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarControl.h b/Frameworks/PSMTabBar/PSMTabBarControl.h deleted file mode 100644 index 6699d0ac5..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarControl.h +++ /dev/null @@ -1,248 +0,0 @@ -// -// PSMTabBarControl.h -// PSMTabBarControl -// -// Created by John Pannell on 10/13/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -/* - This view provides a control interface to manage a regular NSTabView. It looks and works like the tabbed browsing interface of many popular browsers. - */ - -#import - -#define PSMTabDragDidEndNotification @"PSMTabDragDidEndNotification" -#define PSMTabDragDidBeginNotification @"PSMTabDragDidBeginNotification" - -#define kPSMTabBarControlHeight 25 - -// internal cell border -#define MARGIN_X 6 -#define MARGIN_Y 5 - -// padding between objects -#define kPSMTabBarCellPadding 4 - -// fixed size objects -#define kPSMMinimumTitleWidth 30 -#define kPSMTabBarIndicatorWidth 16.0f -#define kPSMTabBarIconWidth 16.0f - -@class PSMOverflowPopUpButton, PSMRolloverButton, PSMTabBarCell, PSMTabBarController; -@protocol PSMTabStyle; - -typedef enum { - PSMTabBarHorizontalOrientation, - PSMTabBarVerticalOrientation -} PSMTabBarOrientation; - -typedef enum { - PSMTabBarTearOffAlphaWindow, - PSMTabBarTearOffMiniwindow -} PSMTabBarTearOffStyle; - -enum { - PSMTab_SelectedMask = 1 << 1, - PSMTab_LeftIsSelectedMask = 1 << 2, - PSMTab_RightIsSelectedMask = 1 << 3, - PSMTab_PositionLeftMask = 1 << 4, - PSMTab_PositionMiddleMask = 1 << 5, - PSMTab_PositionRightMask = 1 << 6, - PSMTab_PositionSingleMask = 1 << 7 -}; - -@interface PSMTabBarControl : NSControl { - // control basics - NSMutableArray *_cells; // the cells that draw the tabs - IBOutlet NSTabView *tabView; // the tab view being navigated - PSMOverflowPopUpButton *_overflowPopUpButton; // for too many tabs - PSMRolloverButton *_addTabButton; - PSMTabBarController *_controller; - - // Spring-loading. - NSTabViewItem *_tabViewItemWithSpring; - - // drawing style - id style; - BOOL _canCloseOnlyTab; - BOOL _disableTabClose; - BOOL _showAddTabButton; - BOOL _sizeCellsToFit; - BOOL _useOverflowMenu; - BOOL _alwaysShowActiveTab; - BOOL _allowsScrubbing; - BOOL _useSafariStyleDragging; - NSInteger _resizeAreaCompensation; - PSMTabBarOrientation _orientation; - PSMTabBarTearOffStyle _tearOffStyle; - - // behavior - BOOL _allowsBackgroundTabClosing; - BOOL _selectsTabsOnMouseDown; - BOOL _createsTabOnDoubleClick; - id _createNewTabTarget; - SEL _createNewTabAction; - id _doubleClickTarget; - SEL _doubleClickAction; - - // vertical tab resizing - BOOL _allowsResizing; - BOOL _resizing; - - // cell width - NSInteger _cellMinWidth; - NSInteger _cellMaxWidth; - NSInteger _cellOptimumWidth; - - IBOutlet id partnerView; // gets resized when hide/show - BOOL _awakenedFromNib; - NSInteger _tabBarWidth; - - // Tracking last window state for update draws - BOOL _lastWindowIsMainCheck; - BOOL _lastAttachedWindowIsMainCheck; - BOOL _lastAppIsActiveCheck; - - // drag and drop - NSEvent *_lastMouseDownEvent; // keep this for dragging reference - BOOL _didDrag; - BOOL _closeClicked; - - // MVC help - IBOutlet id delegate; -} - -// control characteristics -+ (NSBundle *)bundle; -- (CGFloat)availableCellWidth; -- (NSRect)genericCellRect; - -// control configuration -- (PSMTabBarOrientation)orientation; -- (void)setOrientation:(PSMTabBarOrientation)value; -- (BOOL)canCloseOnlyTab; -- (void)setCanCloseOnlyTab:(BOOL)value; -- (BOOL)disableTabClose; -- (void)setDisableTabClose:(BOOL)value; -- (id)style; -- (void)setStyle:(id )newStyle; -- (NSString *)styleName; -- (void)setStyleNamed:(NSString *)name; -- (BOOL)showAddTabButton; -- (void)setShowAddTabButton:(BOOL)value; - -- (id)createNewTabTarget; -- (void)setCreateNewTabTarget:(id)object; -- (SEL)createNewTabAction; -- (void)setCreateNewTabAction:(SEL)selector; - -- (id)doubleClickTarget; -- (void)setDoubleClickTarget:(id)object; -- (SEL)doubleClickAction; -- (void)setDoubleClickAction:(SEL)selector; - -- (NSInteger)cellMinWidth; -- (void)setCellMinWidth:(NSInteger)value; -- (NSInteger)cellMaxWidth; -- (void)setCellMaxWidth:(NSInteger)value; -- (NSInteger)cellOptimumWidth; -- (void)setCellOptimumWidth:(NSInteger)value; -- (BOOL)sizeCellsToFit; -- (void)setSizeCellsToFit:(BOOL)value; -- (BOOL)useOverflowMenu; -- (void)setUseOverflowMenu:(BOOL)value; -- (BOOL)allowsBackgroundTabClosing; -- (void)setAllowsBackgroundTabClosing:(BOOL)value; -- (BOOL)allowsResizing; -- (void)setAllowsResizing:(BOOL)value; -- (BOOL)selectsTabsOnMouseDown; -- (void)setSelectsTabsOnMouseDown:(BOOL)value; -- (BOOL)createsTabOnDoubleClick; -- (void)setCreatesTabOnDoubleClick:(BOOL)value; -- (BOOL)alwaysShowActiveTab; -- (void)setAlwaysShowActiveTab:(BOOL)value; -- (BOOL)allowsScrubbing; -- (void)setAllowsScrubbing:(BOOL)value; -- (BOOL)usesSafariStyleDragging; -- (void)setUsesSafariStyleDragging:(BOOL)value; -- (PSMTabBarTearOffStyle)tearOffStyle; -- (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; - -// accessors -- (NSTabView *)tabView; -- (void)setTabView:(NSTabView *)view; -- (id)delegate; -- (void)setDelegate:(id)object; -- (id)partnerView; -- (void)setPartnerView:(id)view; - -// the buttons -- (PSMRolloverButton *)addTabButton; -- (PSMOverflowPopUpButton *)overflowPopUpButton; - -// actions -- (void)tabClick:(id)sender; -- (void)overflowMenuAction:(id)sender; - -// tab information -- (NSMutableArray *)representedTabViewItems; -- (NSUInteger)numberOfVisibleTabs; -- (PSMTabBarCell *)lastVisibleTab; - -// internal bindings methods also used by the tab drag assistant -- (void)bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item; -- (void)removeTabForCell:(PSMTabBarCell *)cell; - -// External drawing accessors -- (void)update; -- (void)updateTabBarAndUpdateTabs:(BOOL)updateTabs; -- (void)updateTabs; - -@end - -@interface NSObject (TabBarControlDelegateMethods) - -//Standard NSTabView methods -- (BOOL)tabView:(NSTabView *)aTabView shouldCloseTabViewItem:(NSTabViewItem *)tabViewItem; -- (void)tabView:(NSTabView *)aTabView didCloseTabViewItem:(NSTabViewItem *)tabViewItem; - -//"Spring-loaded" tabs methods -- (NSArray *)allowedDraggedTypesForTabView:(NSTabView *)aTabView; -- (void)tabView:(NSTabView *)aTabView acceptedDraggingInfo:(id )draggingInfo onTabViewItem:(NSTabViewItem *)tabViewItem; - -//Contextual menu method -- (NSMenu *)tabView:(NSTabView *)aTabView menuForTabViewItem:(NSTabViewItem *)tabViewItem; - -//Drag and drop methods -- (BOOL)tabView:(NSTabView *)aTabView shouldDragTabViewItem:(NSTabViewItem *)tabViewItem fromTabBar:(PSMTabBarControl *)tabBarControl; -- (BOOL)tabView:(NSTabView *)aTabView shouldDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl; -- (BOOL)tabView:(NSTabView *)aTabView shouldAllowTabViewItem:(NSTabViewItem *)tabViewItem toLeaveTabBar:(PSMTabBarControl *)tabBarControl; -- (void)tabView:(NSTabView*)aTabView didDropTabViewItem:(NSTabViewItem *)tabViewItem inTabBar:(PSMTabBarControl *)tabBarControl; -- (void)draggingEvent:(id )dragEvent enteredTabBar:(PSMTabBarControl *)tabBarControl tabView:(NSTabViewItem *)tabViewItem; -- (void)tabViewDragWindowCreated:(NSWindow *)dragWindow; - -//Tear-off tabs methods -- (NSImage *)tabView:(NSTabView *)aTabView imageForTabViewItem:(NSTabViewItem *)tabViewItem offset:(NSSize *)offset styleMask:(NSUInteger *)styleMask; -- (PSMTabBarControl *)tabView:(NSTabView *)aTabView newTabBarForDraggedTabViewItem:(NSTabViewItem *)tabViewItem atPoint:(NSPoint)point; -- (void)tabView:(NSTabView *)aTabView closeWindowForLastTabViewItem:(NSTabViewItem *)tabViewItem; - -//Overflow menu validation -- (BOOL)tabView:(NSTabView *)aTabView validateOverflowMenuItem:(NSMenuItem *)menuItem forTabViewItem:(NSTabViewItem *)tabViewItem; -- (void)tabView:(NSTabView *)aTabView tabViewItem:(NSTabViewItem *)tabViewItem isInOverflowMenu:(BOOL)inOverflowMenu; - -//tab bar hiding methods -- (void)tabView:(NSTabView *)aTabView tabBarDidHide:(PSMTabBarControl *)tabBarControl; -- (void)tabView:(NSTabView *)aTabView tabBarDidUnhide:(PSMTabBarControl *)tabBarControl; -- (CGFloat)desiredWidthForVerticalTabBar:(PSMTabBarControl *)tabBarControl; - -//closing -- (BOOL)tabView:(NSTabView *)aTabView disableTabCloseForTabViewItem:(NSTabViewItem *)tabViewItem; - -//tooltips -- (NSString *)tabView:(NSTabView *)aTabView toolTipForTabViewItem:(NSTabViewItem *)tabViewItem; - -//accessibility -- (NSString *)accessibilityStringForTabView:(NSTabView *)aTabView objectCount:(NSInteger)objectCount; - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarControl.m b/Frameworks/PSMTabBar/PSMTabBarControl.m deleted file mode 100644 index 20681d7fa..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarControl.m +++ /dev/null @@ -1,1709 +0,0 @@ -// -// PSMTabBarControl.m -// PSMTabBarControl -// -// Created by John Pannell on 10/13/05. -// Copyright 2005 Positive Spin Media. All rights reserved. -// - -#import "PSMTabBarControl.h" -#import "PSMTabBarCell.h" -#import "PSMOverflowPopUpButton.h" -#import "PSMRolloverButton.h" -#import "PSMTabStyle.h" -#import "PSMSequelProTabStyle.h" -#import "PSMTabDragAssistant.h" -#import "PSMTabBarController.h" -#include /* for GetKeys() and KeyMap */ -#include - -#import "SPDatabaseDocument.h" -#import "sequel-ace-Swift.h" - -@interface PSMTabBarControl (Private) - - // constructor/destructor -- (void)initAddedProperties; - - // accessors -- (NSEvent *)lastMouseDownEvent; -- (void)setLastMouseDownEvent:(NSEvent *)event; - - // contents -- (void)addTabViewItem:(NSTabViewItem *)item; -- (void)removeTabForCell:(PSMTabBarCell *)cell; - - // draw -- (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell; -- (void)_positionOverflowMenu; -- (void)_checkWindowFrame; -- (void)updateTabBarAndUpdateTabs:(BOOL)updateTabs; - - // actions -- (void)closeTabClick:(id)sender; - - // notification handlers -- (void)frameDidChange:(NSNotification *)notification; -- (void)windowDidMove:(NSNotification *)aNotification; -- (void)windowDidUpdate:(NSNotification *)notification; -- (void)windowStatusDidChange:(NSNotification *)notification; - - // NSTabView delegate -- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem; -- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem; -- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem; -- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)tabView; - - // archiving -- (void)encodeWithCoder:(NSCoder *)aCoder; -- (instancetype)initWithCoder:(NSCoder *)aDecoder; - - // convenience -- (void)_bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item; -- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame; -@end - -@implementation PSMTabBarControl - -#pragma mark - -#pragma mark Characteristics -+ (NSBundle *)bundle; -{ - static NSBundle *bundle = nil; - if (!bundle) bundle = [NSBundle bundleForClass:[PSMTabBarControl class]]; - return bundle; -} - -/*! - @method availableCellWidth - @abstract The number of pixels available for cells - @discussion Calculates the number of pixels available for cells based on margins and the window resize badge. - @returns Returns the amount of space for cells. -*/ - -- (CGFloat)availableCellWidth -{ - return [self frame].size.width - [style leftMarginForTabBarControl] - [style rightMarginForTabBarControl] - _resizeAreaCompensation; -} - -/*! - @method genericCellRect - @abstract The basic rect for a tab cell. - @discussion Creates a generic frame for a tab cell based on the current control state. - @returns Returns a basic rect for a tab cell. -*/ - -- (NSRect)genericCellRect -{ - NSRect aRect=[self frame]; - aRect.origin.x = [style leftMarginForTabBarControl]; - aRect.origin.y = 0.0f; - aRect.size.width = [self availableCellWidth]; - aRect.size.height = [style tabCellHeight]; - return aRect; -} - -- (void)layout { - [_addTabButton setUsualImage:[style addTabButtonImage]]; - - [super layout]; -} - -#pragma mark - -#pragma mark Constructor/destructor - -- (void)initAddedProperties -{ - _cells = [[NSMutableArray alloc] initWithCapacity:10]; - _controller = [[PSMTabBarController alloc] initWithTabBarControl:self]; - _lastWindowIsMainCheck = NO; - _lastAttachedWindowIsMainCheck = NO; - _lastAppIsActiveCheck = NO; - _lastMouseDownEvent = nil; - - // default config - _orientation = PSMTabBarHorizontalOrientation; - _canCloseOnlyTab = NO; - _disableTabClose = NO; - _showAddTabButton = NO; - _sizeCellsToFit = NO; - _awakenedFromNib = NO; - _useOverflowMenu = YES; - _allowsBackgroundTabClosing = YES; - _allowsResizing = NO; - _selectsTabsOnMouseDown = NO; - _alwaysShowActiveTab = NO; - _allowsScrubbing = NO; - _useSafariStyleDragging = NO; - _cellMinWidth = 100; - _cellMaxWidth = 280; - _cellOptimumWidth = 130; - _tearOffStyle = PSMTabBarTearOffAlphaWindow; - - style = [[PSMSequelProTabStyle alloc] init]; - - // the overflow button/menu - NSRect overflowButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 0, [style rightMarginForTabBarControl] - 1, [self frame].size.height); - _overflowPopUpButton = [[PSMOverflowPopUpButton alloc] initWithFrame:overflowButtonRect pullsDown:YES]; - [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin]; - [_overflowPopUpButton setHidden:YES]; - [self addSubview:_overflowPopUpButton]; - [self _positionOverflowMenu]; - - // new tab button - NSRect addTabButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 3.0f, 16.0f, 16.0f); - _addTabButton = [[PSMRolloverButton alloc] initWithFrame:addTabButtonRect]; - - if (_addTabButton) { - NSImage *newButtonImage = [style addTabButtonImage]; - if (newButtonImage) { - [_addTabButton setUsualImage:newButtonImage]; - } - [_addTabButton setTitle:@""]; - [_addTabButton setImagePosition:NSImageOnly]; - [_addTabButton setButtonType:NSMomentaryChangeButton]; - [_addTabButton setBordered:NO]; - [_addTabButton setBezelStyle:NSShadowlessSquareBezelStyle]; - [self addSubview:_addTabButton]; - - if (_showAddTabButton) { - [_addTabButton setHidden:NO]; - } else { - [_addTabButton setHidden:YES]; - } - [_addTabButton setNeedsDisplay:YES]; - } -} - -- (instancetype)initWithFrame:(NSRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - // Initialization - [self initAddedProperties]; - [self registerForDraggedTypes:@[@"PSMTabBarControlItemPBType"]]; - - // resize - [self setPostsFrameChangedNotifications:YES]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification object:self]; - } - [self setTarget:self]; - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - //unbind all the items to prevent crashing - //not sure if this is necessary or not - NSArray *cells = [NSArray arrayWithArray:_cells]; // create a copy as we will change the original array while being enumerated - NSEnumerator *enumerator = [cells objectEnumerator]; - PSMTabBarCell *nextCell; - while ( (nextCell = [enumerator nextObject]) ) { - [self removeTabForCell:nextCell]; - } - - [self unregisterDraggedTypes]; -} - -- (void)awakeFromNib -{ - // build cells from existing tab view items - NSArray *existingItems = [tabView tabViewItems]; - NSEnumerator *e = [existingItems objectEnumerator]; - NSTabViewItem *item; - while ( (item = [e nextObject]) ) { - if (![[self representedTabViewItems] containsObject:item]) { - [self addTabViewItem:item]; - } - } -} - -- (void)viewWillMoveToWindow:(NSWindow *)aWindow { - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - - [center removeObserver:self name:NSWindowDidBecomeMainNotification object:nil]; - [center removeObserver:self name:NSWindowDidResignMainNotification object:nil]; - [center removeObserver:self name:NSWindowDidUpdateNotification object:nil]; - [center removeObserver:self name:NSWindowDidMoveNotification object:nil]; - - if (aWindow) { - [center addObserver:self selector:@selector(windowStatusDidChange:) name:NSWindowDidBecomeMainNotification object:aWindow]; - [center addObserver:self selector:@selector(windowStatusDidChange:) name:NSWindowDidResignMainNotification object:aWindow]; - [center addObserver:self selector:@selector(windowDidUpdate:) name:NSWindowDidUpdateNotification object:aWindow]; - [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:aWindow]; - } -} - -/** - * Allow a window to be redrawn in response to changes in position or focus level. - */ -- (void)windowStatusDidChange:(NSNotification *)notification -{ - [self setNeedsDisplay:YES]; -} - -#pragma mark - -#pragma mark Accessors - -- (NSMutableArray *)cells -{ - return _cells; -} - -- (NSEvent *)lastMouseDownEvent -{ - return _lastMouseDownEvent; -} - -- (void)setLastMouseDownEvent:(NSEvent *)event -{ - _lastMouseDownEvent = event; -} - -- (id)delegate -{ - return delegate; -} - -- (void)setDelegate:(id)object -{ - delegate = object; - - NSMutableArray *types = [NSMutableArray arrayWithObjects:@"PSMTabBarControlItemPBType", NSStringPboardType,nil]; - - //Update the allowed drag types - if ([self delegate] && [[self delegate] respondsToSelector:@selector(allowedDraggedTypesForTabView:)]) { - [types addObjectsFromArray:[[self delegate] allowedDraggedTypesForTabView:tabView]]; - } - [self unregisterDraggedTypes]; - [self registerForDraggedTypes:types]; -} - -- (NSTabView *)tabView -{ - return tabView; -} - -- (void)setTabView:(NSTabView *)view -{ - tabView = view; -} - -- (id)style -{ - return style; -} - -- (NSString *)styleName -{ - return [style name]; -} - -- (void)setStyle:(id )newStyle -{ - if (style != newStyle) { - style = newStyle; - - // restyle add tab button - if (_addTabButton) { - NSImage *newButtonImage = [style addTabButtonImage]; - if (newButtonImage) { - [_addTabButton setUsualImage:newButtonImage]; - } - } - - [self update]; - } -} - -- (void)setStyleNamed:(NSString *)name -{ - id newStyle; - - if ([name isEqualToString:@"SequelPro"]) { - newStyle = [[PSMSequelProTabStyle alloc] init]; - } - else { - newStyle = [[PSMSequelProTabStyle alloc] init]; - } - - [self setStyle:newStyle]; -} - -- (PSMTabBarOrientation)orientation -{ - return _orientation; -} - -- (void)setOrientation:(PSMTabBarOrientation)value -{ - PSMTabBarOrientation lastOrientation = _orientation; - _orientation = value; - - if (_tabBarWidth < 10) { - _tabBarWidth = 120; - } - - if (lastOrientation != _orientation) { - [[self style] setOrientation:_orientation]; - - [self _positionOverflowMenu]; //move the overflow popup button to the right place - [self update]; - } -} - -- (BOOL)canCloseOnlyTab -{ - return _canCloseOnlyTab; -} - -- (void)setCanCloseOnlyTab:(BOOL)value -{ - _canCloseOnlyTab = value; - if ([_cells count] == 1) { - [self update]; - } -} - -- (BOOL)disableTabClose -{ - return _disableTabClose; -} - -- (void)setDisableTabClose:(BOOL)value -{ - _disableTabClose = value; - [self update]; -} - -- (BOOL)showAddTabButton -{ - return _showAddTabButton; -} - -- (void)setShowAddTabButton:(BOOL)value -{ - _showAddTabButton = value; - if (!NSIsEmptyRect([_controller addButtonRect])) - [_addTabButton setFrame:[_controller addButtonRect]]; - - [_addTabButton setHidden:!_showAddTabButton]; - [_addTabButton setNeedsDisplay:YES]; - - [self update]; -} - -- (id)createNewTabTarget -{ - return _createNewTabTarget; -} - -- (void)setCreateNewTabTarget:(id)object -{ - _createNewTabTarget = object; - [[self addTabButton] setTarget:object]; -} - -- (SEL)createNewTabAction -{ - return _createNewTabAction; -} - -- (void)setCreateNewTabAction:(SEL)selector -{ - _createNewTabAction = selector; - [[self addTabButton] setAction:selector]; -} - -- (id)doubleClickTarget -{ - return _doubleClickTarget; -} - -- (void)setDoubleClickTarget:(id)object -{ - _doubleClickTarget = object; -} - -- (SEL)doubleClickAction -{ - return _doubleClickAction; -} - -- (void)setDoubleClickAction:(SEL)selector -{ - _doubleClickAction = selector; -} - -- (NSInteger)cellMinWidth -{ - return _cellMinWidth; -} - -- (void)setCellMinWidth:(NSInteger)value -{ - _cellMinWidth = value; - [self update]; -} - -- (NSInteger)cellMaxWidth -{ - return _cellMaxWidth; -} - -- (void)setCellMaxWidth:(NSInteger)value -{ - _cellMaxWidth = value; - [self update]; -} - -- (NSInteger)cellOptimumWidth -{ - return _cellOptimumWidth; -} - -- (void)setCellOptimumWidth:(NSInteger)value -{ - _cellOptimumWidth = value; - [self update]; -} - -- (BOOL)sizeCellsToFit -{ - return _sizeCellsToFit; -} - -- (void)setSizeCellsToFit:(BOOL)value -{ - _sizeCellsToFit = value; - [self update]; -} - -- (BOOL)useOverflowMenu -{ - return _useOverflowMenu; -} - -- (void)setUseOverflowMenu:(BOOL)value -{ - _useOverflowMenu = value; - [self update]; -} - -- (PSMRolloverButton *)addTabButton -{ - return _addTabButton; -} - -- (PSMOverflowPopUpButton *)overflowPopUpButton -{ - return _overflowPopUpButton; -} - -- (BOOL)allowsBackgroundTabClosing -{ - return _allowsBackgroundTabClosing; -} - -- (void)setAllowsBackgroundTabClosing:(BOOL)value -{ - _allowsBackgroundTabClosing = value; -} - -- (BOOL)allowsResizing -{ - return _allowsResizing; -} - -- (void)setAllowsResizing:(BOOL)value -{ - _allowsResizing = value; -} - -- (BOOL)selectsTabsOnMouseDown -{ - return _selectsTabsOnMouseDown; -} - -- (void)setSelectsTabsOnMouseDown:(BOOL)value -{ - _selectsTabsOnMouseDown = value; -} - -- (BOOL)createsTabOnDoubleClick; -{ - return _createsTabOnDoubleClick; -} - -- (void)setCreatesTabOnDoubleClick:(BOOL)value -{ - _createsTabOnDoubleClick = value; -} - -- (BOOL)alwaysShowActiveTab -{ - return _alwaysShowActiveTab; -} - -- (void)setAlwaysShowActiveTab:(BOOL)value -{ - _alwaysShowActiveTab = value; -} - -- (BOOL)allowsScrubbing -{ - return _allowsScrubbing; -} - -- (void)setAllowsScrubbing:(BOOL)value -{ - _allowsScrubbing = value; -} - -- (BOOL)usesSafariStyleDragging -{ - return _useSafariStyleDragging; -} - -- (void)setUsesSafariStyleDragging:(BOOL)value -{ - _useSafariStyleDragging = value; -} - -- (PSMTabBarTearOffStyle)tearOffStyle -{ - return _tearOffStyle; -} - -- (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle -{ - _tearOffStyle = tearOffStyle; -} - -#pragma mark - -#pragma mark Functionality - -- (void)addTabViewItem:(NSTabViewItem *)item -{ - // create cell - PSMTabBarCell *cell = [[PSMTabBarCell alloc] initWithControlView:self]; - NSRect cellRect, lastCellFrame = [[_cells lastObject] frame]; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { - cellRect = [self genericCellRect]; - cellRect.size.width = 30; - cellRect.origin.x = lastCellFrame.origin.x + lastCellFrame.size.width; - } else { - cellRect = /*lastCellFrame*/[self genericCellRect]; - cellRect.size.width = lastCellFrame.size.width; - cellRect.size.height = 0; - cellRect.origin.y = lastCellFrame.origin.y + lastCellFrame.size.height; - } - - [cell setRepresentedObject:item]; - [cell setFrame:cellRect]; - - // bind it up - [self bindPropertiesForCell:cell andTabViewItem:item]; - - // add to collection - [_cells addObject:cell]; - if ((NSInteger)[_cells count] == [tabView numberOfTabViewItems]) { - [self update]; // don't update unless all are accounted for! - } -} - -- (void)removeTabForCell:(PSMTabBarCell *)cell { - NSTabViewItem *item = [cell representedObject]; - - // unbind - [[cell indicator] unbind:@"animate"]; - [[cell indicator] unbind:@"hidden"]; - [cell unbind:@"hasIcon"]; - [cell unbind:@"hasLargeImage"]; - [cell unbind:@"title"]; - [cell unbind:@"count"]; - [cell unbind:@"countColor"]; - [cell unbind:@"isEdited"]; - - SPDatabaseDocument *databaseDocument = [item databaseDocument]; - - if (databaseDocument) { - if ([databaseDocument respondsToSelector:@selector(isProcessing)]) { - [databaseDocument removeObserver:cell forKeyPath:@"isProcessing"]; - } - if ([databaseDocument respondsToSelector:@selector(icon)]) { - [databaseDocument removeObserver:cell forKeyPath:@"icon"]; - } - if ([databaseDocument respondsToSelector:@selector(count)]) { - [databaseDocument removeObserver:cell forKeyPath:@"objectCount"]; - } - if ([databaseDocument respondsToSelector:@selector(countColor)]) { - [databaseDocument removeObserver:cell forKeyPath:@"countColor"]; - } - if ([databaseDocument respondsToSelector:@selector(largeImage)]) { - [databaseDocument removeObserver:cell forKeyPath:@"largeImage"]; - } - if ([databaseDocument respondsToSelector:@selector(isEdited)]) { - [databaseDocument removeObserver:cell forKeyPath:@"isEdited"]; - } - } - - // stop watching identifier - [item removeObserver:self forKeyPath:@"identifier"]; - - // remove indicator - if ([[self subviews] containsObject:[cell indicator]]) { - [[cell indicator] removeFromSuperview]; - } - if(cell != nil){ - // remove tracking - [[NSNotificationCenter defaultCenter] removeObserver:cell]; - - if ([cell closeButtonTrackingTag] != 0) { - [self removeTrackingRect:[cell closeButtonTrackingTag]]; - [cell setCloseButtonTrackingTag:0]; - } - if ([cell cellTrackingTag] != 0) { - [self removeTrackingRect:[cell cellTrackingTag]]; - [cell setCellTrackingTag:0]; - } - - // pull from collection - [_cells removeObject:cell]; - } - else{ - SPLog(@"cell is nil"); - } - - [self update]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - // did the tab's identifier change? - if ([keyPath isEqualToString:@"identifier"]) { - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - if ([cell representedObject] == object) { - [self _bindPropertiesForCell:cell andTabViewItem:object]; - } - } - } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -#pragma mark - -#pragma mark Hide/Show - -- (void)updateTabs { - if (!_awakenedFromNib) { - return; - } - - [[self subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; - - [self addSubview:_overflowPopUpButton]; - [self addSubview:_addTabButton]; - - CGFloat partnerOriginalSize, partnerOriginalOrigin, myOriginalSize, myOriginalOrigin, partnerTargetSize, partnerTargetOrigin, myTargetSize, myTargetOrigin; - - // target values for partner - if ([self orientation] == PSMTabBarHorizontalOrientation) { - // current (original) values - myOriginalSize = [self frame].size.height; - myOriginalOrigin = [self frame].origin.y; - if (partnerView) { - partnerOriginalSize = [partnerView frame].size.height; - partnerOriginalOrigin = [partnerView frame].origin.y; - } else { - partnerOriginalSize = [[self window] frame].size.height; - partnerOriginalOrigin = [[self window] frame].origin.y; - } - myTargetSize = kPSMTabBarControlHeight; - - if (partnerView) { - partnerTargetSize = partnerOriginalSize + myOriginalSize - myTargetSize; - - // above or below me? - if ((myOriginalOrigin - kPSMTabBarControlHeight) > partnerOriginalOrigin) { - - // partner is below me, keeps its origin - partnerTargetOrigin = partnerOriginalOrigin; - myTargetOrigin = myOriginalOrigin + myOriginalSize - myTargetSize; - } else { - - // partner is above me, I keep my origin - myTargetOrigin = myOriginalOrigin; - partnerTargetOrigin = partnerOriginalOrigin + myOriginalSize - myTargetSize; - } - } else { - - // for window movement - myTargetOrigin = myOriginalOrigin; - partnerTargetOrigin = partnerOriginalOrigin + myOriginalSize - myTargetSize; - partnerTargetSize = partnerOriginalSize - myOriginalSize + myTargetSize; - } - } else /* vertical */ { - // current (original) values - myOriginalSize = [self frame].size.width; - myOriginalOrigin = [self frame].origin.x; - if (partnerView) { - partnerOriginalSize = [partnerView frame].size.width; - partnerOriginalOrigin = [partnerView frame].origin.x; - } else { - partnerOriginalSize = [[self window] frame].size.width; - partnerOriginalOrigin = [[self window] frame].origin.x; - } - - if (partnerView) { - //to the left or right? - if (myOriginalOrigin < partnerOriginalOrigin + partnerOriginalSize) { - // partner is to the left - // I'm growing - myTargetOrigin = myOriginalOrigin; - myTargetSize = myOriginalSize + _tabBarWidth; - partnerTargetOrigin = partnerOriginalOrigin + _tabBarWidth; - partnerTargetSize = partnerOriginalSize - _tabBarWidth; - } else { - // partner is to the right - // I'm growing - myTargetOrigin = myOriginalOrigin - _tabBarWidth; - myTargetSize = myOriginalSize + _tabBarWidth; - partnerTargetOrigin = partnerOriginalOrigin; - partnerTargetSize = partnerOriginalSize - _tabBarWidth; - } - } else { - // I'm growing - myTargetOrigin = myOriginalOrigin; - myTargetSize = _tabBarWidth; - partnerTargetOrigin = partnerOriginalOrigin - _tabBarWidth + 1; - partnerTargetSize = partnerOriginalSize + _tabBarWidth - 1; - } - - if ([[self delegate] respondsToSelector:@selector(desiredWidthForVerticalTabBar:)]) { - myTargetSize = [[self delegate] desiredWidthForVerticalTabBar:self]; - } - } - - // moves the frame of the tab bar and window (or partner view) linearly to hide or show the tab bar - NSRect myFrame = [self frame]; - CGFloat myCurrentOrigin = (myOriginalOrigin + ((myTargetOrigin - myOriginalOrigin))); - CGFloat myCurrentSize = (myOriginalSize + ((myTargetSize - myOriginalSize))); - CGFloat partnerCurrentOrigin = (partnerOriginalOrigin + ((partnerTargetOrigin - partnerOriginalOrigin))); - CGFloat partnerCurrentSize = (partnerOriginalSize + ((partnerTargetSize - partnerOriginalSize))); - - NSRect myNewFrame; - if ([self orientation] == PSMTabBarHorizontalOrientation) { - myNewFrame = NSMakeRect(myFrame.origin.x, myCurrentOrigin, myFrame.size.width, myCurrentSize); - } else { - myNewFrame = NSMakeRect(myCurrentOrigin, myFrame.origin.y, myCurrentSize, myFrame.size.height); - } - - if (partnerView) { - // resize self and view - NSRect resizeRect; - if ([self orientation] == PSMTabBarHorizontalOrientation) { - resizeRect = NSMakeRect([partnerView frame].origin.x, partnerCurrentOrigin, [partnerView frame].size.width, partnerCurrentSize); - } else { - resizeRect = NSMakeRect(partnerCurrentOrigin, [partnerView frame].origin.y, partnerCurrentSize, [partnerView frame].size.height); - } - [partnerView setFrame:resizeRect]; - [partnerView setNeedsDisplay:YES]; - [self setFrame:myNewFrame]; - } else { - // resize self and window - NSRect resizeRect; - if ([self orientation] == PSMTabBarHorizontalOrientation) { - resizeRect = NSMakeRect([[self window] frame].origin.x, partnerCurrentOrigin, [[self window] frame].size.width, partnerCurrentSize); - } else { - resizeRect = NSMakeRect(partnerCurrentOrigin, [[self window] frame].origin.y, partnerCurrentSize, [[self window] frame].size.height); - } - [[self window] setFrame:resizeRect display:YES]; - [self setFrame:myNewFrame]; - } - - [self viewDidEndLiveResize]; - [self update]; - if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:tabBarDidUnhide:)]) { - [[self delegate] tabView:[self tabView] tabBarDidUnhide:self]; - } - [[self window] display]; -} - -- (id)partnerView -{ - return partnerView; -} - -- (void)setPartnerView:(id)view -{ - partnerView = view; -} - -#pragma mark - -#pragma mark Drawing - -- (BOOL)isFlipped -{ - return YES; -} - -- (void)drawRect:(NSRect)rect -{ - [style drawTabBar:self inRect:rect]; -} - -- (void)update -{ - [self updateTabBarAndUpdateTabs:YES]; -} - -- (void)updateTabBarAndUpdateTabs:(BOOL)updateTabs -{ - // make sure all of our tabs are accounted for before updating, - // or only proceed if a drag is in progress (where counts may mismatch) - if ([[self tabView] numberOfTabViewItems] != (NSInteger)[_cells count] && ![[PSMTabDragAssistant sharedDragAssistant] isDragging]) { - return; - } - - if (updateTabs) { - [self updateTabs]; - } - - [self removeAllToolTips]; - [_controller layoutCells]; //eventually we should only have to call this when we know something has changed - - PSMTabBarCell *currentCell; - - NSMenu *overflowMenu = [_controller overflowMenu]; - [_overflowPopUpButton setHidden:(overflowMenu == nil)]; - [_overflowPopUpButton setMenu:overflowMenu]; - - for (NSUInteger i = 0; i < [_cells count]; i++) { - currentCell = [_cells objectAtIndex:i]; - [currentCell setFrame:[_controller cellFrameAtIndex:i]]; - - if (![currentCell isInOverflowMenu]) { - [self _setupTrackingRectsForCell:currentCell]; - } - } - - [_addTabButton setFrame:[_controller addButtonRect]]; - [_addTabButton setHidden:!_showAddTabButton]; - [self setNeedsDisplay:YES]; -} - -- (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell -{ - - // Skip tracking rects for placeholders - not required. - if ([cell isPlaceholder]) return; - - NSInteger tag; - NSUInteger anIndex = [_cells indexOfObject:cell]; - NSRect cellTrackingRect = [_controller cellTrackingRectAtIndex:anIndex]; - NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; - BOOL mouseInCell = NSMouseInRect(mousePoint, cellTrackingRect, [self isFlipped]); - - // If dragging, suppress mouse interaction - if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) mouseInCell = NO; - - //set the cell tracking rect - [self removeTrackingRect:[cell cellTrackingTag]]; - tag = [self addTrackingRect:cellTrackingRect owner:cell userData:nil assumeInside:mouseInCell]; - [cell setCellTrackingTag:tag]; - [cell setHighlighted:mouseInCell]; - - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { - NSRect closeRect = [_controller closeButtonTrackingRectAtIndex:anIndex]; - BOOL mouseInCloseRect = NSMouseInRect(mousePoint, closeRect, [self isFlipped]); - - //set the close button tracking rect - [self removeTrackingRect:[cell closeButtonTrackingTag]]; - tag = [self addTrackingRect:closeRect owner:cell userData:nil assumeInside:mouseInCloseRect]; - [cell setCloseButtonTrackingTag:tag]; - } - - //set the tooltip tracking rect - [self addToolTipRect:[cell frame] owner:self userData:nil]; -} - -- (void)_positionOverflowMenu -{ - NSRect cellRect, frame = [self frame]; - cellRect.size.height = [style tabCellHeight]; - cellRect.size.width = [style rightMarginForTabBarControl]; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { - cellRect.origin.y = 0; - cellRect.origin.x = frame.size.width - [style rightMarginForTabBarControl] + (_resizeAreaCompensation ? -(_resizeAreaCompensation - 1) : 1); - [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin]; - } else { - cellRect.origin.x = 0; - cellRect.origin.y = frame.size.height - [style tabCellHeight]; - cellRect.size.width = frame.size.width; - [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin | NSViewMinYMargin]; - } - - [_overflowPopUpButton setFrame:cellRect]; -} - -- (void)_checkWindowFrame -{ - //figure out if the new frame puts the control in the way of the resize widget - NSWindow *window = [self window]; - - if (window) { - NSRect resizeWidgetFrame = [[window contentView] frame]; - resizeWidgetFrame.origin.x += resizeWidgetFrame.size.width - 22; - resizeWidgetFrame.size.width = 22; - resizeWidgetFrame.size.height = 22; - - if ([window showsResizeIndicator] && NSIntersectsRect([self frame], resizeWidgetFrame)) { - //the resize widgets are larger on metal windows - _resizeAreaCompensation = [window styleMask] & NSWindowStyleMaskTexturedBackground ? 20 : 8; - } else { - _resizeAreaCompensation = 0; - } - - [self _positionOverflowMenu]; - } -} - -#pragma mark - -#pragma mark Mouse Tracking - -- (BOOL)mouseDownCanMoveWindow -{ - return NO; -} - -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent -{ - return YES; -} - -- (void)mouseDown:(NSEvent *)theEvent -{ - _didDrag = NO; - - // keep for dragging - [self setLastMouseDownEvent:theEvent]; - // what cell? - NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - NSRect frame = [self frame]; - - if ([self orientation] == PSMTabBarVerticalOrientation && [self allowsResizing] && partnerView && (mousePt.x > frame.size.width - 3)) { - _resizing = YES; - } - - NSRect cellFrame; - PSMTabBarCell *cell = [self cellForPoint:mousePt cellFrame:&cellFrame]; - if (cell) { - BOOL overClose = NSMouseInRect(mousePt, [cell closeButtonRectForFrame:cellFrame], [self isFlipped]); - if (overClose && - ![self disableTabClose] && - ![cell isCloseButtonSuppressed] && - ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]] || [theEvent modifierFlags] & NSEventModifierFlagCommand)) { - _closeClicked = YES; - } - else if ([theEvent clickCount] == 2) { - [_doubleClickTarget performSelector:_doubleClickAction withObject:cell]; - } else if (_selectsTabsOnMouseDown) { - [self performSelector:@selector(tabClick:) withObject:cell]; - } - [self setNeedsDisplay:YES]; - } else { - if ([theEvent clickCount] == 2) { - // fire create new tab - if ([self createsTabOnDoubleClick] && [self createNewTabTarget] != nil && [self createNewTabAction] != nil) { - [[self createNewTabTarget] performSelector:[self createNewTabAction]]; - } - return; - } - } -} - -- (void)mouseDragged:(NSEvent *)theEvent -{ - if (![self lastMouseDownEvent]) { - return; - } - - NSPoint currentPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - - if (_resizing) { - NSRect frame = [self frame]; - CGFloat resizeAmount = [theEvent deltaX]; - if ((currentPoint.x > frame.size.width && resizeAmount > 0) || (currentPoint.x < frame.size.width && resizeAmount < 0)) { - [[NSCursor resizeLeftRightCursor] push]; - - NSRect partnerFrame = [partnerView frame]; - - //do some bounds checking - if ((frame.size.width + resizeAmount > [self cellMinWidth]) && (frame.size.width + resizeAmount < [self cellMaxWidth])) { - frame.size.width += resizeAmount; - partnerFrame.size.width -= resizeAmount; - partnerFrame.origin.x += resizeAmount; - - [self setFrame:frame]; - [partnerView setFrame:partnerFrame]; - [[self superview] setNeedsDisplay:YES]; - } - } - return; - } - - NSRect cellFrame; - NSPoint trackingStartPoint = [self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil]; - PSMTabBarCell *cell = [self cellForPoint:trackingStartPoint cellFrame:&cellFrame]; - if (cell) { - //check to see if the close button was the target in the clicked cell - //highlight/unhighlight the close button as necessary - NSRect iconRect = [cell closeButtonRectForFrame:cellFrame]; - - if (_closeClicked && NSMouseInRect(trackingStartPoint, iconRect, [self isFlipped]) && - ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]])) { - [self setNeedsDisplay:YES]; - return; - } - - CGFloat dx = fabs(currentPoint.x - trackingStartPoint.x); - CGFloat dy = fabs(currentPoint.y - trackingStartPoint.y); - CGFloat distance = sqrtf(dx * dx + dy * dy); - - if (distance >= 10 && !_didDrag && ![[PSMTabDragAssistant sharedDragAssistant] isDragging] && - [self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDragTabViewItem:fromTabBar:)] && - [[self delegate] tabView:tabView shouldDragTabViewItem:[cell representedObject] fromTabBar:self]) { - _didDrag = YES; - [[PSMTabDragAssistant sharedDragAssistant] startDraggingCell:cell fromTabBar:self withMouseDownEvent:[self lastMouseDownEvent]]; - } - } -} - -- (void)mouseUp:(NSEvent *)theEvent -{ - if (![self lastMouseDownEvent]) { - return; - } - - if (_resizing) { - _resizing = NO; - [[NSCursor arrowCursor] set]; - } else { - // what cell? - NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - NSRect cellFrame, mouseDownCellFrame; - PSMTabBarCell *cell = [self cellForPoint:mousePt cellFrame:&cellFrame]; - PSMTabBarCell *mouseDownCell = [self cellForPoint:[self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil] cellFrame:&mouseDownCellFrame]; - if (cell) { - NSPoint trackingStartPoint = [self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil]; - NSRect iconRect = [mouseDownCell closeButtonRectForFrame:mouseDownCellFrame]; - - if ((NSMouseInRect(mousePt, iconRect,[self isFlipped])) && ![self disableTabClose] && ![cell isCloseButtonSuppressed]) { - if (([[NSApp currentEvent] modifierFlags] & NSEventModifierFlagOption) != 0) { - //If the user is holding Option, close all other tabs - NSEnumerator *enumerator = [[[self cells] copy] objectEnumerator]; - PSMTabBarCell *otherCell; - - while ((otherCell = [enumerator nextObject])) { - if (otherCell != cell) - [self performSelector:@selector(closeTabClick:) withObject:otherCell]; - } - } else { - //Otherwise, close this tab - [self performSelector:@selector(closeTabClick:) withObject:cell]; - } - - } else if (NSMouseInRect(mousePt, mouseDownCellFrame, [self isFlipped]) && - (!NSMouseInRect(trackingStartPoint, [cell closeButtonRectForFrame:cellFrame], [self isFlipped]) || ![self allowsBackgroundTabClosing] || [self disableTabClose])) { - // If -[self selectsTabsOnMouseDown] is TRUE, we already performed tabClick: on mouseDown. - if (![self selectsTabsOnMouseDown]) { - [self performSelector:@selector(tabClick:) withObject:cell]; - } - - } - } - - _closeClicked = NO; - } - - // Clear the last mouse down event to prevent drag issues - [self setLastMouseDownEvent:nil]; -} - -- (NSMenu *)menuForEvent:(NSEvent *)event -{ - NSMenu *menu = nil; - NSTabViewItem *item = [[self cellForPoint:[self convertPoint:[event locationInWindow] fromView:nil] cellFrame:nil] representedObject]; - - if (item && [[self delegate] respondsToSelector:@selector(tabView:menuForTabViewItem:)]) { - menu = [[self delegate] tabView:tabView menuForTabViewItem:item]; - } - return menu; -} - -#pragma mark - -#pragma mark Drag and Drop - -- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent -{ - return YES; -} - -// NSDraggingSource - -- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context{ - - return (context == NSDraggingContextWithinApplication ? NSDragOperationMove : NSDragOperationNone); -} - -- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session{ - return YES; -} - -- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint{ - [[PSMTabDragAssistant sharedDragAssistant] draggingBeganAt:screenPoint]; -} - -- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint{ - [[PSMTabDragAssistant sharedDragAssistant] draggingMovedTo:screenPoint]; - -} - -// NSDraggingDestination -- (NSDragOperation)draggingEntered:(id )sender -{ - if([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { - - if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { - return NSDragOperationNone; - } - - [[PSMTabDragAssistant sharedDragAssistant] draggingEnteredTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; - return NSDragOperationMove; - } - - return NSDragOperationNone; -} - -- (NSDragOperation)draggingUpdated:(id )sender -{ - - if ([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { - - if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { - return NSDragOperationNone; - } - - [[PSMTabDragAssistant sharedDragAssistant] draggingUpdatedInTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; - return NSDragOperationMove; - } - - PSMTabBarCell *cell = [self cellForPoint:[self convertPoint:[sender draggingLocation] fromView:nil] cellFrame:nil]; - if (cell) { - //something that was accepted by the delegate was dragged on - - // Notify the delegate to respond to drag events if supported. This allows custom - // behaviour when dragging certain drag types onto the tab - for example changing the - // view appropriately. - if ([self delegate] && [[self delegate] respondsToSelector:@selector(draggingEvent:enteredTabBar:tabView:)]) { - [[self delegate] draggingEvent:sender enteredTabBar:self tabView:[cell representedObject]]; - } - return NSDragOperationCopy; - } - - return NSDragOperationNone; -} - -- (void)draggingExited:(id )sender -{ - - [[PSMTabDragAssistant sharedDragAssistant] draggingExitedTabBar:self]; -} - -- (BOOL)prepareForDragOperation:(id )sender -{ - //validate the drag operation only if there's a valid tab bar to drop into - return [[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] == NSNotFound || - [[PSMTabDragAssistant sharedDragAssistant] destinationTabBar] != nil; -} - -- (BOOL)performDragOperation:(id )sender -{ - if ([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { - [[PSMTabDragAssistant sharedDragAssistant] performDragOperation]; - } else if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:acceptedDraggingInfo:onTabViewItem:)]) { - //forward the drop to the delegate - [[self delegate] tabView:tabView acceptedDraggingInfo:sender onTabViewItem:[[self cellForPoint:[self convertPoint:[sender draggingLocation] fromView:nil] cellFrame:nil] representedObject]]; - } - return YES; -} - -- (void)draggingSession:(NSDraggingSession *)session - endedAtPoint:(NSPoint)screenPoint - operation:(NSDragOperation)operation{ - - [[PSMTabDragAssistant sharedDragAssistant] draggedImageEndedAt:screenPoint operation:operation]; -} - -- (void)concludeDragOperation:(id )sender -{ -} - -#pragma mark - -#pragma mark Actions - -- (void)overflowMenuAction:(id)sender -{ - NSTabViewItem *tabViewItem = (NSTabViewItem *)[sender representedObject]; - [tabView selectTabViewItem:tabViewItem]; -} - -- (void)closeTabClick:(id)sender -{ - NSTabViewItem *item = [sender representedObject]; - if(([_cells count] == 1) && (![self canCloseOnlyTab])) - return; - - if ([[self delegate] respondsToSelector:@selector(tabView:shouldCloseTabViewItem:)]) { - if (![[self delegate] tabView:tabView shouldCloseTabViewItem:item]) { - return; - } - } - - if(item) { - [tabView removeTabViewItem:item]; - } -} - -- (void)tabClick:(id)sender -{ - [tabView selectTabViewItem:[sender representedObject]]; -} - -- (void)frameDidChange:(NSNotification *)notification -{ - [self _checkWindowFrame]; - [self updateTabBarAndUpdateTabs:NO]; -} - -- (void)viewDidMoveToWindow -{ - [self _checkWindowFrame]; -} - -- (void)viewWillStartLiveResize -{ - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - [[cell indicator] stopAnimation:self]; - } - [self setNeedsDisplay:YES]; -} - --(void)viewDidEndLiveResize -{ - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - [[cell indicator] startAnimation:self]; - } - - [self _checkWindowFrame]; - [self update]; -} - -- (void)resetCursorRects -{ - [super resetCursorRects]; - if ([self orientation] == PSMTabBarVerticalOrientation) { - NSRect frame = [self frame]; - [self addCursorRect:NSMakeRect(frame.size.width - 2, 0, 2, frame.size.height) cursor:[NSCursor resizeLeftRightCursor]]; - } -} - -- (void)windowDidMove:(NSNotification *)aNotification -{ - [self setNeedsDisplay:YES]; -} - -- (void)windowDidUpdate:(NSNotification *)notification -{ - // Determine whether a draw update in response to window state change might be required - BOOL isMainWindow = [[self window] isMainWindow]; - BOOL attachedWindowIsMainWindow = [[[self window] attachedSheet] isMainWindow]; - BOOL isActiveApplication = [NSApp isActive]; - if (_lastWindowIsMainCheck != isMainWindow || _lastAttachedWindowIsMainCheck != attachedWindowIsMainWindow || _lastAppIsActiveCheck != isActiveApplication) { - _lastWindowIsMainCheck = isMainWindow; - _lastAttachedWindowIsMainCheck = attachedWindowIsMainWindow; - _lastAppIsActiveCheck = isActiveApplication; - - // Allow the tab bar to redraw itself in result to window ordering/sheet/etc changes - [self setNeedsDisplay:YES]; - } -} - -#pragma mark - -#pragma mark Menu Validation - -- (BOOL)validateMenuItem:(NSMenuItem *)sender -{ - [sender setState:([[sender representedObject] isEqualTo:[tabView selectedTabViewItem]]) ? NSOnState : NSOffState]; - - return [[self delegate] respondsToSelector:@selector(tabView:validateOverflowMenuItem:forTabViewItem:)] ? - [[self delegate] tabView:[self tabView] validateOverflowMenuItem:sender forTabViewItem:[sender representedObject]] : YES; -} - -#pragma mark - -#pragma mark NSTabView Delegate - -- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - // here's a weird one - this message is sent before the "tabViewDidChangeNumberOfTabViewItems" - // message, thus I can end up updating when there are no cells, if no tabs were (yet) present - NSInteger tabIndex = [aTabView indexOfTabViewItem:tabViewItem]; - - if ([_cells count] > 0 && tabIndex < (NSInteger)[_cells count]) { - PSMTabBarCell *thisCell = [_cells objectAtIndex:tabIndex]; - if (_alwaysShowActiveTab && [thisCell isInOverflowMenu]) { - - //temporarily disable the delegate in order to move the tab to a different index - id tempDelegate = [aTabView delegate]; - [aTabView setDelegate:nil]; - - // move it all around first - [aTabView removeTabViewItem:tabViewItem]; - [aTabView insertTabViewItem:tabViewItem atIndex:0]; - [_cells removeObjectAtIndex:tabIndex]; - [_cells insertObject:thisCell atIndex:0]; - [thisCell setIsInOverflowMenu:NO]; //very important else we get a fun recursive loop going - [[_cells objectAtIndex:[_cells count] - 1] setIsInOverflowMenu:YES]; //these 2 lines are pretty uncool and this logic needs to be updated - - [aTabView setDelegate:tempDelegate]; - - //reset the selection since removing it changed the selection - [aTabView selectTabViewItem:tabViewItem]; - - [self update]; - } else { - [_controller setSelectedCell:thisCell]; - [self setNeedsDisplay:YES]; - } - } - - if ([[self delegate] respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) { - [[self delegate] performSelector:@selector(tabView:didSelectTabViewItem:) withObject:aTabView withObject:tabViewItem]; - } -} - -- (BOOL)tabView:(NSTabView *)aTabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[self delegate] respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) { - return [[self delegate] tabView:aTabView shouldSelectTabViewItem:tabViewItem]; - } else { - return YES; - } -} -- (void)tabView:(NSTabView *)aTabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[self delegate] respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) { - [[self delegate] performSelector:@selector(tabView:willSelectTabViewItem:) withObject:aTabView withObject:tabViewItem]; - } -} - -- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView -{ - NSArray *tabItems = [tabView tabViewItems]; - // go through cells, remove any whose representedObjects are not in [tabView tabViewItems] - NSEnumerator *e = [[_cells copy] objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - //remove the observer binding - if ([cell representedObject] && ![tabItems containsObject:[cell representedObject]]) { - // see issue #2609 - // -removeTabForCell: comes first to stop the observing that would be triggered in the delegate's call tree - // below and finally caused a crash. - [self removeTabForCell:cell]; - - if ([[self delegate] respondsToSelector:@selector(tabView:didCloseTabViewItem:)]) { - [[self delegate] tabView:aTabView didCloseTabViewItem:[cell representedObject]]; - } - } - } - - // go through tab view items, add cell for any not present - NSMutableArray *cellItems = [self representedTabViewItems]; - NSEnumerator *ex = [tabItems objectEnumerator]; - NSTabViewItem *item; - while ( (item = [ex nextObject]) ) { - if (![cellItems containsObject:item]) { - [self addTabViewItem:item]; - } - } - - // pass along for other delegate responses - if ([[self delegate] respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)]) { - [[self delegate] performSelector:@selector(tabViewDidChangeNumberOfTabViewItems:) withObject:aTabView]; - } - - // reset cursor tracking for the add tab button if one exists - if ([self addTabButton]) [[self addTabButton] resetCursorRects]; -} - -#pragma mark - -#pragma mark Tooltips - -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData -{ - if ([[self delegate] respondsToSelector:@selector(tabView:toolTipForTabViewItem:)]) { - return [[self delegate] tabView:[self tabView] toolTipForTabViewItem:[[self cellForPoint:point cellFrame:nil] representedObject]]; - } - return nil; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_cells forKey:@"PSMcells"]; - [aCoder encodeObject:tabView forKey:@"PSMtabView"]; - [aCoder encodeObject:_overflowPopUpButton forKey:@"PSMoverflowPopUpButton"]; - [aCoder encodeObject:_addTabButton forKey:@"PSMaddTabButton"]; - [aCoder encodeObject:style forKey:@"PSMstyle"]; - [aCoder encodeInteger:_orientation forKey:@"PSMorientation"]; - [aCoder encodeBool:_canCloseOnlyTab forKey:@"PSMcanCloseOnlyTab"]; - [aCoder encodeBool:_disableTabClose forKey:@"PSMdisableTabClose"]; - [aCoder encodeBool:_allowsBackgroundTabClosing forKey:@"PSMallowsBackgroundTabClosing"]; - [aCoder encodeBool:_allowsResizing forKey:@"PSMallowsResizing"]; - [aCoder encodeBool:_selectsTabsOnMouseDown forKey:@"PSMselectsTabsOnMouseDown"]; - [aCoder encodeBool:_showAddTabButton forKey:@"PSMshowAddTabButton"]; - [aCoder encodeBool:_sizeCellsToFit forKey:@"PSMsizeCellsToFit"]; - [aCoder encodeInteger:_cellMinWidth forKey:@"PSMcellMinWidth"]; - [aCoder encodeInteger:_cellMaxWidth forKey:@"PSMcellMaxWidth"]; - [aCoder encodeInteger:_cellOptimumWidth forKey:@"PSMcellOptimumWidth"]; - [aCoder encodeObject:partnerView forKey:@"PSMpartnerView"]; - [aCoder encodeBool:_awakenedFromNib forKey:@"PSMawakenedFromNib"]; - [aCoder encodeObject:_lastMouseDownEvent forKey:@"PSMlastMouseDownEvent"]; - [aCoder encodeObject:delegate forKey:@"PSMdelegate"]; - [aCoder encodeBool:_useOverflowMenu forKey:@"PSMuseOverflowMenu"]; - [aCoder encodeBool:_alwaysShowActiveTab forKey:@"PSMalwaysShowActiveTab"]; - } -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - self = [super initWithCoder:aDecoder]; - if (self) { - - // Initialization - [self initAddedProperties]; - [self registerForDraggedTypes:@[@"PSMTabBarControlItemPBType"]]; - - if ([aDecoder allowsKeyedCoding]) { - _cells = [aDecoder decodeObjectForKey:@"PSMcells"]; - tabView = [aDecoder decodeObjectForKey:@"PSMtabView"]; - _overflowPopUpButton = [aDecoder decodeObjectForKey:@"PSMoverflowPopUpButton"]; - _addTabButton = [aDecoder decodeObjectForKey:@"PSMaddTabButton"]; - style = [aDecoder decodeObjectForKey:@"PSMstyle"]; - _orientation = (PSMTabBarOrientation)[aDecoder decodeIntegerForKey:@"PSMorientation"]; - _canCloseOnlyTab = [aDecoder decodeBoolForKey:@"PSMcanCloseOnlyTab"]; - _disableTabClose = [aDecoder decodeBoolForKey:@"PSMdisableTabClose"]; - _allowsBackgroundTabClosing = [aDecoder decodeBoolForKey:@"PSMallowsBackgroundTabClosing"]; - _allowsResizing = [aDecoder decodeBoolForKey:@"PSMallowsResizing"]; - _selectsTabsOnMouseDown = [aDecoder decodeBoolForKey:@"PSMselectsTabsOnMouseDown"]; - _showAddTabButton = [aDecoder decodeBoolForKey:@"PSMshowAddTabButton"]; - _sizeCellsToFit = [aDecoder decodeBoolForKey:@"PSMsizeCellsToFit"]; - _cellMinWidth = [aDecoder decodeIntegerForKey:@"PSMcellMinWidth"]; - _cellMaxWidth = [aDecoder decodeIntegerForKey:@"PSMcellMaxWidth"]; - _cellOptimumWidth = [aDecoder decodeIntegerForKey:@"PSMcellOptimumWidth"]; - partnerView = [aDecoder decodeObjectForKey:@"PSMpartnerView"]; - _awakenedFromNib = [aDecoder decodeBoolForKey:@"PSMawakenedFromNib"]; - _lastMouseDownEvent = [aDecoder decodeObjectForKey:@"PSMlastMouseDownEvent"]; - _useOverflowMenu = [aDecoder decodeBoolForKey:@"PSMuseOverflowMenu"]; - _alwaysShowActiveTab = [aDecoder decodeBoolForKey:@"PSMalwaysShowActiveTab"]; - delegate = [aDecoder decodeObjectForKey:@"PSMdelegate"]; - } - - // resize - [self setPostsFrameChangedNotifications:YES]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification object:self]; - } - - [self setTarget:self]; - return self; -} - -#pragma mark - -#pragma mark IB Palette - -- (NSSize)minimumFrameSizeFromKnobPosition:(NSInteger)position -{ - return NSMakeSize(100.0f, 22.0f); -} - -- (NSSize)maximumFrameSizeFromKnobPosition:(NSInteger)knobPosition -{ - return NSMakeSize(10000.0f, 22.0f); -} - -- (void)placeView:(NSRect)newFrame -{ - // this is called any time the view is resized in IB - [self setFrame:newFrame]; - [self update]; -} - -#pragma mark - -#pragma mark Convenience - -- (void)bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item -{ - [self _bindPropertiesForCell:cell andTabViewItem:item]; - - // watch for changes in the identifier - [item addObserver:self forKeyPath:@"identifier" options:0 context:nil]; -} - -- (void)_bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item { - - SPDatabaseDocument *databaseDocument = [item databaseDocument]; - // bind the indicator to the represented object's status (if it exists) - [[cell indicator] setHidden:YES]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(isProcessing)]) { - NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; - [bindingOptions setObject:NSNegateBooleanTransformerName forKey:@"NSValueTransformerName"]; - [[cell indicator] bind:@"animate" toObject:databaseDocument withKeyPath:@"isProcessing" options:nil]; - [[cell indicator] bind:@"hidden" toObject:databaseDocument withKeyPath:@"isProcessing" options:bindingOptions]; - [databaseDocument addObserver:cell forKeyPath:@"isProcessing" options:0 context:nil]; - } - } - - // bind for the existence of an icon - [cell setHasIcon:NO]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(icon)]) { - NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; - [bindingOptions setObject:NSIsNotNilTransformerName forKey:@"NSValueTransformerName"]; - [cell bind:@"hasIcon" toObject:databaseDocument withKeyPath:@"icon" options:bindingOptions]; - [databaseDocument addObserver:cell forKeyPath:@"icon" options:0 context:nil]; - } - } - - // bind for the existence of a counter - [cell setCount:0]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(count)]) { - [cell bind:@"count" toObject:databaseDocument withKeyPath:@"objectCount" options:nil]; - [databaseDocument addObserver:cell forKeyPath:@"objectCount" options:0 context:nil]; - } - } - - // bind for the color of a counter - [cell setCountColor:nil]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(countColor)]) { - [cell bind:@"countColor" toObject:databaseDocument withKeyPath:@"countColor" options:nil]; - [databaseDocument addObserver:cell forKeyPath:@"countColor" options:0 context:nil]; - } - } - - // bind for a large image - [cell setHasLargeImage:NO]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(largeImage)]) { - NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; - [bindingOptions setObject:NSIsNotNilTransformerName forKey:@"NSValueTransformerName"]; - [cell bind:@"hasLargeImage" toObject:databaseDocument withKeyPath:@"largeImage" options:bindingOptions]; - [databaseDocument addObserver:cell forKeyPath:@"largeImage" options:0 context:nil]; - } - } - - [cell setIsEdited:NO]; - if (databaseDocument != nil) { - if ([databaseDocument respondsToSelector:@selector(isEdited)]) { - [cell bind:@"isEdited" toObject:databaseDocument withKeyPath:@"isEdited" options:nil]; - [databaseDocument addObserver:cell forKeyPath:@"isEdited" options:0 context:nil]; - } - } - - // bind my string value to the label on the represented tab - [cell bind:@"title" toObject:item withKeyPath:@"label" options:nil]; - [cell bind:@"backgroundColor" toObject:item withKeyPath:@"color" options:nil]; -} - -- (NSMutableArray *)representedTabViewItems -{ - NSMutableArray *temp = [NSMutableArray arrayWithCapacity:[_cells count]]; - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject])) { - if ([cell representedObject]) { - [temp addObject:[cell representedObject]]; - } - } - return temp; -} - -- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame -{ - if ([self orientation] == PSMTabBarHorizontalOrientation && !NSPointInRect(point, [self genericCellRect])) { - return nil; - } - - NSInteger i, cnt = [_cells count]; - for (i = 0; i < cnt; i++) { - PSMTabBarCell *cell = [_cells objectAtIndex:i]; - - if (NSPointInRect(point, [cell frame])) { - if (outFrame) { - *outFrame = [cell frame]; - } - return cell; - } - } - return nil; -} - -- (PSMTabBarCell *)lastVisibleTab { - NSInteger i, cellCount = [_cells count]; - for (i = 0; i < cellCount; i++) { - if ([[_cells objectAtIndex:i] isInOverflowMenu]) { - return [_cells objectAtIndex:(i - 1)]; - } - } - return [_cells objectAtIndex:(cellCount - 1)]; -} - -- (NSUInteger)numberOfVisibleTabs { - NSUInteger i, cellCount = 0; - PSMTabBarCell *nextCell; - - for (i = 0; i < [_cells count]; i++) { - nextCell = [_cells objectAtIndex:i]; - - if ([nextCell isInOverflowMenu]) { - break; - } - - if (![nextCell isPlaceholder]) { - cellCount++; - } - } - - return cellCount; -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarController.h b/Frameworks/PSMTabBar/PSMTabBarController.h deleted file mode 100644 index f970b103c..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarController.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// PSMTabBarController.h -// PSMTabBarControl -// -// Created by Kent Sutherland on 11/24/06. -// Copyright 2006 Kent Sutherland. All rights reserved. -// - -#import - -@class PSMTabBarControl, PSMTabBarCell; - -@interface PSMTabBarController : NSObject -{ - PSMTabBarControl *_control; - NSMutableArray *_cellTrackingRects, *_closeButtonTrackingRects; - NSMutableArray *_cellFrames; - NSRect _addButtonRect; - NSMenu *_overflowMenu; -} - -- (instancetype)initWithTabBarControl:(PSMTabBarControl *)control; - -- (NSRect)addButtonRect; -- (NSMenu *)overflowMenu; -- (NSRect)cellTrackingRectAtIndex:(NSUInteger)anIndex; -- (NSRect)closeButtonTrackingRectAtIndex:(NSUInteger)anIndex; -- (NSRect)cellFrameAtIndex:(NSUInteger)anIndex; - -- (void)setSelectedCell:(PSMTabBarCell *)cell; - -- (void)layoutCells; - -@end - -@interface NSObject (TabRepresentedObjectIdentifierMethods) - -// Method for generating a tooltip for a tab -- (NSString *)tabTitleForTooltip; - -// Retrieving whether a tab is working -- (BOOL)isProcessing; - -@end diff --git a/Frameworks/PSMTabBar/PSMTabBarController.m b/Frameworks/PSMTabBar/PSMTabBarController.m deleted file mode 100644 index 917798433..000000000 --- a/Frameworks/PSMTabBar/PSMTabBarController.m +++ /dev/null @@ -1,661 +0,0 @@ -// -// PSMTabBarController.m -// PSMTabBarControl -// -// Created by Kent Sutherland on 11/24/06. -// Copyright 2006 Kent Sutherland. All rights reserved. -// - -#import "PSMTabBarController.h" -#import "PSMTabBarControl.h" -#import "PSMTabBarCell.h" -#import "PSMTabStyle.h" -#import "NSString_AITruncation.h" -#import "PSMTabDragAssistant.h" -#import "PSMRolloverButton.h" - -#define MAX_OVERFLOW_MENUITEM_TITLE_LENGTH 60 - -@interface PSMTabBarController (Private) -- (NSArray *)_generateWidthsFromCells:(NSArray *)cells; -- (void)_setupCells:(NSArray *)cells withWidths:(NSArray *)widths; -@end - -@implementation PSMTabBarController - -/*! - @method initWithTabBarControl: - @abstract Creates a new PSMTabBarController instance. - @discussion Creates a new PSMTabBarController for controlling a PSMTabBarControl. Should only be called by - PSMTabBarControl. - @param A PSMTabBarControl. - @returns A newly created PSMTabBarController instance. -*/ - -- (instancetype)initWithTabBarControl:(PSMTabBarControl *)control -{ - if ( (self = [super init]) ) { - _control = control; - _cellTrackingRects = [[NSMutableArray alloc] init]; - _closeButtonTrackingRects = [[NSMutableArray alloc] init]; - _cellFrames = [[NSMutableArray alloc] init]; - _addButtonRect = NSZeroRect; - } - return self; -} - -/*! - @method addButtonRect - @abstract Returns the position for the add tab button. - @discussion Returns the position for the add tab button. - @returns The rect for the add button rect. -*/ - -- (NSRect)addButtonRect -{ - return _addButtonRect; -} - -/*! - @method overflowMenu - @abstract Returns current overflow menu or nil if there is none. - @discussion Returns current overflow menu or nil if there is none. - @returns The current overflow menu. -*/ - -- (NSMenu *)overflowMenu -{ - return _overflowMenu; -} - -/*! - @method cellTrackingRectAtIndex: - @abstract Returns the rect for the tracking rect at the requested index. - @discussion Returns the rect for the tracking rect at the requested index. - @param Index of a cell. - @returns The tracking rect of the cell at the requested index. -*/ - -- (NSRect)cellTrackingRectAtIndex:(NSUInteger)anIndex -{ - NSRect rect; - if (anIndex < [_cellTrackingRects count]) { - rect = [[_cellTrackingRects objectAtIndex:anIndex] rectValue]; - } else { - NSLog(@"cellTrackingRectAtIndex: Invalid index (%lu)", (unsigned long)anIndex); - rect = NSZeroRect; - } - return rect; -} - -/*! - @method closeButtonTrackingRectAtIndex: - @abstract Returns the tracking rect for the close button at the requested index. - @discussion Returns the tracking rect for the close button at the requested index. - @param Index of a cell. - @returns The close button tracking rect of the cell at the requested index. -*/ - -- (NSRect)closeButtonTrackingRectAtIndex:(NSUInteger)anIndex -{ - NSRect rect; - if (anIndex < [_closeButtonTrackingRects count]) { - rect = [[_closeButtonTrackingRects objectAtIndex:anIndex] rectValue]; - } else { - NSLog(@"closeButtonTrackingRectAtIndex: Invalid index (%lu)", (unsigned long)anIndex); - rect = NSZeroRect; - } - return rect; -} - -/*! - @method cellFrameAtIndex: - @abstract Returns the frame for the cell at the requested index. - @discussion Returns the frame for the cell at the requested index. - @param Index of a cell. - @returns The frame of the cell at the requested index. -*/ - -- (NSRect)cellFrameAtIndex:(NSUInteger)anIndex -{ - NSRect rect; - - if (anIndex < [_cellFrames count]) { - rect = [[_cellFrames objectAtIndex:anIndex] rectValue]; - } else { - NSLog(@"cellFrameAtIndex: Invalid index (%lu)", (unsigned long)anIndex); - rect = NSZeroRect; - } - return rect; -} - -/*! - @method setSelectedCell: - @abstract Changes the cell states so the given cell is the currently selected cell. - @discussion Makes the given cell the active cell and properly recalculates the tab states for surrounding cells. - @param An instance of PSMTabBarCell to make active. -*/ - -- (void)setSelectedCell:(PSMTabBarCell *)cell -{ - NSArray *cells = [_control cells]; - NSEnumerator *enumerator = [cells objectEnumerator]; - PSMTabBarCell *lastCell = nil, *nextCell; - - //deselect the previously selected tab - while ( (nextCell = [enumerator nextObject]) && ([nextCell state] == NSOffState) ) { - lastCell = nextCell; - } - - [nextCell setState:NSOffState]; - [nextCell setTabState:PSMTab_PositionMiddleMask]; - - if (lastCell && lastCell != [_control lastVisibleTab]) { - [lastCell setTabState:~[lastCell tabState] & PSMTab_RightIsSelectedMask]; - } - - if ( (nextCell = [enumerator nextObject]) ) { - [nextCell setTabState:~[lastCell tabState] & PSMTab_LeftIsSelectedMask]; - } - - [cell setState:NSOnState]; - [cell setTabState:PSMTab_SelectedMask]; - - if (![cell isInOverflowMenu]) { - NSUInteger cellIndex = [cells indexOfObject:cell]; - - if (cellIndex > 0) { - nextCell = [cells objectAtIndex:cellIndex - 1]; - [nextCell setTabState:[nextCell tabState] | PSMTab_RightIsSelectedMask]; - } - - if (cellIndex < [cells count] - 1) { - nextCell = [cells objectAtIndex:cellIndex + 1]; - [nextCell setTabState:[nextCell tabState] | PSMTab_LeftIsSelectedMask]; - } - } -} - -/*! - @method layoutCells - @abstract Recalculates cell positions and states. - @discussion This method calculates the proper frame, tabState and overflow menu status for all cells in the - tab bar control. -*/ - -- (void)layoutCells -{ - NSArray *cells = [_control cells]; - NSInteger cellCount = [cells count]; - - // make sure all of our tabs are accounted for before updating, - // or only proceed if a drag is in progress (where counts may mismatch) - if ([[_control tabView] numberOfTabViewItems] != cellCount && ![[PSMTabDragAssistant sharedDragAssistant] isDragging]) { - return; - } - - // - [_cellTrackingRects removeAllObjects]; - [_closeButtonTrackingRects removeAllObjects]; - [_cellFrames removeAllObjects]; - - NSArray *cellWidths = [self _generateWidthsFromCells:cells]; - [self _setupCells:cells withWidths:cellWidths]; - - //set up the rect from the add tab button - _addButtonRect = [_control genericCellRect]; - _addButtonRect.size = [_control.addTabButton frame].size; - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - _addButtonRect.origin.y = MARGIN_Y; - _addButtonRect.origin.x += [[cellWidths valueForKeyPath:@"@sum.floatValue"] floatValue] + MARGIN_X; - } else { - _addButtonRect.origin.x = 0; - _addButtonRect.origin.y = [[cellWidths lastObject] floatValue]; - } -} - -/*! - * @method _shrinkWidths:towardMinimum:withAvailableWidth: - * @abstract Decreases widths in an array toward a minimum until they fit within availableWidth, if possible - * @param An array of NSNumbers - * @param The target minimum - * @param The maximum available width - * @returns The amount by which the total array width was shrunk - */ -- (NSInteger)_shrinkWidths:(NSMutableArray *)newWidths towardMinimum:(NSInteger)minimum withAvailableWidth:(CGFloat)availableWidth -{ - BOOL changed = NO; - NSInteger count = [newWidths count]; - NSInteger totalWidths = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; - NSInteger originalTotalWidths = totalWidths; - - do { - changed = NO; - - NSInteger q = 0; - for (q = (count - 1); q >= 0; q--) { - CGFloat cellWidth = [[newWidths objectAtIndex:q] floatValue]; - if (cellWidth - 1 >= minimum) { - cellWidth--; - totalWidths--; - - [newWidths replaceObjectAtIndex:q - withObject:[NSNumber numberWithDouble:cellWidth]]; - - changed = YES; - } - } - - } while (changed && (totalWidths > availableWidth)); - - return (originalTotalWidths - totalWidths); -} - -/*! - * @function potentialMinimumForArray() - * @abstract Calculate the minimum total for a given array of widths - * @discussion The array is summed using, for each item, the minimum between the current value and the passed minimum value. - * This is useful for getting a sum if the array has size-to-fit widths which will be allowed to be less than the - * specified minimum. - * @param An array of widths - * @param The minimum - * @returns The smallest possible sum for the array - */ -static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) -{ - NSInteger runningTotal = 0; - NSInteger count = [array count]; - - NSInteger i = 0; - for (i = 0; i < count; i++) { - NSInteger currentValue = [[array objectAtIndex:i] integerValue]; - runningTotal += MIN(currentValue, minimum); - } - - return runningTotal; -} - -/*! - @method _generateWidthsFromCells: - @abstract Calculates the width of cells that would be visible. - @discussion Calculates the width of cells in the tab bar and returns an array of widths for the cells that would be - visible. Uses large blocks of code that were previously in PSMTabBarControl's update method. - @param An array of PSMTabBarCells. - @returns An array of numbers representing the widths of cells that would be visible. -*/ - -- (NSArray *)_generateWidthsFromCells:(NSArray *)cells -{ - NSInteger cellCount = [cells count], i, numberOfVisibleCells = ([_control orientation] == PSMTabBarHorizontalOrientation) ? 1 : 0; - NSMutableArray *newWidths = [NSMutableArray arrayWithCapacity:cellCount]; - id style = [_control style]; - CGFloat availableWidth = [_control availableCellWidth], currentOrigin = 0, totalOccupiedWidth = 0.0f, width; - NSRect cellRect = [_control genericCellRect], controlRect = [_control frame]; - PSMTabBarCell *currentCell; - - if ([_control orientation] == PSMTabBarVerticalOrientation) { - currentOrigin = [style topMarginForTabBarControl]; - } - - //Don't let cells overlap the add tab button if it is visible - if ([_control showAddTabButton]) { - availableWidth -= [self addButtonRect].size.width; - } - - for (i = 0; i < cellCount; i++) { - currentCell = [cells objectAtIndex:i]; - - // supress close button? - [currentCell setCloseButtonSuppressed:((cellCount == 1 && [_control canCloseOnlyTab] == NO) || - [_control disableTabClose] || - ([[_control delegate] respondsToSelector:@selector(tabView:disableTabCloseForTabViewItem:)] && - [[_control delegate] tabView:[_control tabView] disableTabCloseForTabViewItem:[currentCell representedObject]]))]; - - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - // Determine cell width - if ([_control sizeCellsToFit]) { - width = [currentCell desiredWidthOfCell]; - if (width > [_control cellMaxWidth]) { - width = [_control cellMaxWidth]; - } - } else { - width = [_control cellOptimumWidth]; - } - - width = ceilf(width); - - //check to see if there is not enough space to place all tabs as preferred - if (totalOccupiedWidth + width >= availableWidth) { - //There's not enough space to add currentCell at its preferred width! - - //If we're not going to use the overflow menu, cram all the tab cells into the bar regardless of minimum width - if (![_control useOverflowMenu]) { - NSInteger j, averageWidth = (availableWidth / cellCount); - - numberOfVisibleCells = cellCount; - [newWidths removeAllObjects]; - - for (j = 0; j < cellCount; j++) { - CGFloat desiredWidth = [[cells objectAtIndex:j] desiredWidthOfCell]; - [newWidths addObject:[NSNumber numberWithDouble:(desiredWidth < averageWidth && [_control sizeCellsToFit]) ? desiredWidth : averageWidth]]; - } - - totalOccupiedWidth = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; - break; - } - - //We'll be using the overflow menu if needed. - numberOfVisibleCells = i; - if ([_control sizeCellsToFit]) { - BOOL remainingCellsMustGoToOverflow = NO; - - totalOccupiedWidth = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; - - /* Can I squeeze it in without violating min cell width? This is the width we would take up - * if every cell so far were at the control minimum size (or their current size if that is less than the control minimum). - */ - if ((potentialMinimumForArray(newWidths, [_control cellMinWidth]) + MIN(width, [_control cellMinWidth])) <= availableWidth) { - /* It's definitely possible for cells so far to be visible. - * Shrink other cells to allow this one to fit - */ - NSInteger cellMinWidth = [_control cellMinWidth]; - - /* Start off adding it to the array; we know that it will eventually fit because - * (the potential minimum <= availableWidth) - * - * This allows average and minimum aggregates on the NSArray to work. - */ - [newWidths addObject:[NSNumber numberWithDouble:width]]; - numberOfVisibleCells++; - - totalOccupiedWidth += width; - - //First, try to shrink tabs toward the average. Tabs smaller than average won't change - totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:[[newWidths valueForKeyPath:@"@avg.intValue"] integerValue] - withAvailableWidth:availableWidth]; - - - - if (totalOccupiedWidth > availableWidth) { - //Next, shrink tabs toward the smallest of the existing tabs. The smallest tab won't change. - NSInteger smallestTabWidth = [[newWidths valueForKeyPath:@"@min.intValue"] integerValue]; - if (smallestTabWidth > cellMinWidth) { - totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:smallestTabWidth - withAvailableWidth:availableWidth]; - } - } - - if (totalOccupiedWidth > availableWidth) { - //Finally, shrink tabs toward the imposed minimum size. All tabs larger than the minimum wll change. - totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:cellMinWidth - withAvailableWidth:availableWidth]; - } - - if (totalOccupiedWidth > availableWidth) { - NSLog(@"**** -[PSMTabBarController generateWidthsFromCells:] This is a failure (available %f, total %f, width is %f)", - availableWidth, totalOccupiedWidth, width); - remainingCellsMustGoToOverflow = YES; - } - - if (totalOccupiedWidth < availableWidth) { - /* We're not using all available space not but exceeded available width before; - * stretch all cells to fully fit the bar - */ - NSInteger leftoverWidth = availableWidth - totalOccupiedWidth; - if (leftoverWidth > 0) { - NSInteger q; - for (q = numberOfVisibleCells - 1; q >= 0; q--) { - NSInteger desiredAddition = (NSInteger)leftoverWidth / (q + 1); - NSInteger newCellWidth = (NSInteger)[[newWidths objectAtIndex:q] doubleValue] + desiredAddition; - [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:newCellWidth]]; - leftoverWidth -= desiredAddition; - totalOccupiedWidth += desiredAddition; - } - } - } - - } else { - // stretch - distribute leftover room among cells, since we can't add this cell - NSInteger leftoverWidth = availableWidth - totalOccupiedWidth; - NSInteger q; - for (q = i - 1; q >= 0; q--) { - NSInteger desiredAddition = (NSInteger)leftoverWidth / (q + 1); - NSInteger newCellWidth = (NSInteger)[[newWidths objectAtIndex:q] doubleValue] + desiredAddition; - [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:newCellWidth]]; - leftoverWidth -= desiredAddition; - } - - remainingCellsMustGoToOverflow = YES; - } - - // done assigning widths; remaining cells go in overflow menu - if (remainingCellsMustGoToOverflow) { - break; - } - - } else { - //We're not using size-to-fit - NSInteger revisedWidth = availableWidth / (i + 1); - if (revisedWidth >= [_control cellMinWidth]) { - NSUInteger q; - totalOccupiedWidth = 0; - - for (q = 0; q < [newWidths count]; q++) { - [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:revisedWidth]]; - totalOccupiedWidth += revisedWidth; - } - // just squeezed this one in... - [newWidths addObject:[NSNumber numberWithDouble:revisedWidth]]; - totalOccupiedWidth += revisedWidth; - numberOfVisibleCells++; - } else { - // couldn't fit that last one... - break; - } - } - } else { - //(totalOccupiedWidth < availableWidth) - numberOfVisibleCells = cellCount; - [newWidths addObject:[NSNumber numberWithDouble:width]]; - totalOccupiedWidth += width; - } - - } else { - //lay out vertical tabs - if (currentOrigin + cellRect.size.height <= controlRect.size.height) { - [newWidths addObject:[NSNumber numberWithDouble:currentOrigin]]; - numberOfVisibleCells++; - currentOrigin += cellRect.size.height; - } else { - //out of room, the remaining tabs go into overflow - if ([newWidths count] > 0 && controlRect.size.height - currentOrigin < 17) { - [newWidths removeLastObject]; - numberOfVisibleCells--; - } - break; - } - } - } - - //make sure there are at least two items in the horizontal tab bar - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - if (numberOfVisibleCells < 2 && [cells count] > 1) { - PSMTabBarCell *cell1 = [cells objectAtIndex:0], *cell2 = [cells objectAtIndex:1]; - NSNumber *cellWidth; - - [newWidths removeAllObjects]; - totalOccupiedWidth = 0; - - cellWidth = [NSNumber numberWithDouble:[cell1 desiredWidthOfCell] < availableWidth * 0.5f ? [cell1 desiredWidthOfCell] : availableWidth * 0.5f]; - [newWidths addObject:cellWidth]; - totalOccupiedWidth += [cellWidth floatValue]; - - cellWidth = [NSNumber numberWithDouble:[cell2 desiredWidthOfCell] < (availableWidth - totalOccupiedWidth) ? [cell2 desiredWidthOfCell] : (availableWidth - totalOccupiedWidth)]; - [newWidths addObject:cellWidth]; - totalOccupiedWidth += [cellWidth floatValue]; - - if (totalOccupiedWidth < availableWidth) { - [newWidths replaceObjectAtIndex:0 withObject:[NSNumber numberWithDouble:availableWidth - [cellWidth doubleValue]]]; - } - - numberOfVisibleCells = 2; - } - } - - return newWidths; -} - -/*! - @method _setupCells:withWidths - @abstract Creates tracking rect arrays and sets the frames of the visible cells. - @discussion Creates tracking rect arrays and sets the cells given in the widths array. -*/ - -- (void)_setupCells:(NSArray *)cells withWidths:(NSArray *)widths -{ - NSUInteger i, tabState, cellCount = [cells count]; - NSRect cellRect = [_control genericCellRect]; - PSMTabBarCell *cell; - NSTabViewItem *selectedTabViewItem = [[_control tabView] selectedTabViewItem]; - NSMenuItem *menuItem; - _overflowMenu = nil; - - for (i = 0; i < cellCount; i++) { - cell = [cells objectAtIndex:i]; - - if (i < [widths count]) { - tabState = 0; - - // set cell frame - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - cellRect.size.width = [[widths objectAtIndex:i] floatValue]; - } else { - cellRect.size.width = [_control frame].size.width; - cellRect.origin.y = [[widths objectAtIndex:i] floatValue]; - cellRect.origin.x = 0; - } - - [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; - - //add tracking rects to arrays - [_closeButtonTrackingRects addObject:[NSValue valueWithRect:[cell closeButtonRectForFrame:cellRect]]]; - [_cellTrackingRects addObject:[NSValue valueWithRect:cellRect]]; - - if ([[cell representedObject] isEqualTo:selectedTabViewItem]) { - [cell setState:NSOnState]; - tabState |= PSMTab_SelectedMask; - // previous cell - if (i > 0) { - [[cells objectAtIndex:i - 1] setTabState:([(PSMTabBarCell *)[cells objectAtIndex:i - 1] tabState] | PSMTab_RightIsSelectedMask)]; - } - // next cell - see below - } else { - [cell setState:NSOffState]; - // see if prev cell was selected - if ( (i > 0) && ([[cells objectAtIndex:i - 1] state] == NSOnState) ) { - tabState |= PSMTab_LeftIsSelectedMask; - } - } - - // more tab states - if ([widths count] == 1) { - tabState |= PSMTab_PositionLeftMask | PSMTab_PositionRightMask | PSMTab_PositionSingleMask; - } else if (i == 0) { - tabState |= PSMTab_PositionLeftMask; - } else if (i == [widths count] - 1) { - tabState |= PSMTab_PositionRightMask; - } - - [cell setTabState:tabState]; - [cell setIsInOverflowMenu:NO]; - - // indicator - if (![[cell indicator] isHidden]) { - if (![[_control subviews] containsObject:[cell indicator]]) { - [_control addSubview:[cell indicator]]; - [[cell indicator] startAnimation:self]; - } - } - - // next... - cellRect.origin.x += [[widths objectAtIndex:i] floatValue]; - } else { - [cell setState:NSOffState]; - [cell setIsInOverflowMenu:YES]; - [[cell indicator] removeFromSuperview]; - - //position the cell well offscreen - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - cellRect.origin.x += [[_control style] rightMarginForTabBarControl] + 20; - } else { - cellRect.origin.y = [_control frame].size.height + 2; - } - - [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; - - if (_overflowMenu == nil) { - _overflowMenu = [[NSMenu alloc] init]; - [_overflowMenu insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:0]; // Because the overflowPupUpButton is a pull down menu - [_overflowMenu setDelegate:self]; - } - - // Each item's title is limited to 60 characters. If more than 60 characters, use an ellipsis to indicate that more exists. - menuItem = [_overflowMenu addItemWithTitle:[[[cell attributedStringValue] string] stringWithEllipsisByTruncatingToLength:MAX_OVERFLOW_MENUITEM_TITLE_LENGTH] - action:@selector(overflowMenuAction:) - keyEquivalent:@""]; - [menuItem setTarget:_control]; - [menuItem setRepresentedObject:[cell representedObject]]; - if([[[cell representedObject] identifier] respondsToSelector:@selector(tabTitleForTooltip)]) - [menuItem setToolTip:[[[cell representedObject] identifier] tabTitleForTooltip]]; - if ([cell count] > 0) { - [menuItem setTitle:[[menuItem title] stringByAppendingFormat:@" (%lu)", (unsigned long)[cell count]]]; - } - } - } -} - -- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)menuItem atIndex:(NSInteger)anIndex shouldCancel:(BOOL)shouldCancel -{ - if (menu == _overflowMenu) { - if ([[[menuItem representedObject] identifier] respondsToSelector:@selector(icon)]) { - [menuItem setImage:[[[menuItem representedObject] identifier] valueForKey:@"icon"]]; - } - } - - return YES; -} - -- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu -{ - if (menu == _overflowMenu) { - return [_overflowMenu numberOfItems]; - - } else { - NSLog(@"Warning: Unexpected menu delegate call for menu %@",menu); - return 0; - } -} - -@end - -/* -PSMTabBarController will store what the current tab frame state should be like based off the last layout. PSMTabBarControl -has to handle fetching the new frame and then changing the tab cell frame. - Tab states will probably be changed immediately. - -Tabs that aren't going to be visible need to have their frame set offscreen. Treat them as if they were visible. - -The overflow menu is rebuilt and stored by the controller. - -Arrays of tracking rects will be created here, but not applied. - Tracking rects are removed and added by PSMTabBarControl at the end of an animate/display cycle. - -The add tab button frame is handled by this controller. Visibility and location are set by the control. - -isInOverflowMenu should probably be removed in favor of a call that returns yes/no to if a cell is in overflow. (Not yet implemented) - -Still need to rewrite most of the code in PSMTabDragAssistant. -*/ diff --git a/Frameworks/PSMTabBar/PSMTabDragAssistant.h b/Frameworks/PSMTabBar/PSMTabDragAssistant.h deleted file mode 100644 index 92a8d4d8d..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragAssistant.h +++ /dev/null @@ -1,103 +0,0 @@ -// -// PSMTabDragAssistant.h -// PSMTabBarControl -// -// Created by John Pannell on 4/10/06. -// Copyright 2006 Positive Spin Media. All rights reserved. -// - -/* - This class is a sigleton that manages the details of a tab drag and drop. The details were beginning to overwhelm me when keeping all of this in the control and cells :-) - */ - -#import -#import "PSMTabBarControl.h" - -#define kPSMTabDragAnimationSteps 8 - -@class PSMTabBarCell, PSMTabDragWindowController; - -@interface PSMTabDragAssistant : NSObject { - PSMTabBarControl *_sourceTabBar; - PSMTabBarControl *_destinationTabBar; - NSMutableSet *_participatingTabBars; - PSMTabBarCell *_draggedCell; - NSInteger _draggedCellIndex; // for snap back - BOOL _isDragging; - - // Support for dragging into new windows - PSMTabDragWindowController *_draggedTab, *_draggedView; - NSSize _dragWindowOffset; - NSTimer *_fadeTimer; - BOOL _centersDragWindows; - PSMTabBarTearOffStyle _currentTearOffStyle; - - // Animation - NSTimer *_animationTimer; - NSMutableArray *_sineCurveWidths; - NSPoint _currentMouseLoc; - PSMTabBarCell *_targetCell; -} - -// Creation/destruction -+ (PSMTabDragAssistant *)sharedDragAssistant; - -// Accessors -- (PSMTabBarControl *)sourceTabBar; -- (void)setSourceTabBar:(PSMTabBarControl *)tabBar; -- (PSMTabBarControl *)destinationTabBar; -- (void)setDestinationTabBar:(PSMTabBarControl *)tabBar; -- (PSMTabBarCell *)draggedCell; -- (void)setDraggedCell:(PSMTabBarCell *)cell; -- (NSInteger)draggedCellIndex; -- (void)setDraggedCellIndex:(NSInteger)value; -- (BOOL)isDragging; -- (void)setIsDragging:(BOOL)value; -- (NSPoint)currentMouseLoc; -- (void)setCurrentMouseLoc:(NSPoint)point; -- (PSMTabBarCell *)targetCell; -- (void)setTargetCell:(PSMTabBarCell *)cell; - -// Functionality -- (void)startDraggingCell:(PSMTabBarCell *)cell fromTabBar:(PSMTabBarControl *)control withMouseDownEvent:(NSEvent *)event; -- (void)draggingEnteredTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc; -- (void)draggingUpdatedInTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc; -- (void)draggingExitedTabBar:(PSMTabBarControl *)control; -- (void)performDragOperation; -- (void)draggedImageEndedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; -- (void)finishDrag; - -- (void)draggingBeganAt:(NSPoint)aPoint; -- (void)draggingMovedTo:(NSPoint)aPoint; - -- (void)fadeInDragWindow:(NSTimer *)timer; -- (void)fadeOutDragWindow:(NSTimer *)timer; - -// Animation -- (void)animateDrag:(NSTimer *)timer; -- (void)calculateDragAnimationForTabBar:(PSMTabBarControl *)control; - -// Placeholder -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control withDraggedCell:(PSMTabBarCell *)cell; -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control; -- (void)removeAllPlaceholdersFromTabBar:(PSMTabBarControl *)control; - -@end - -@interface PSMTabBarControl (DragAccessors) - -- (id)style; -- (NSMutableArray *)cells; -- (void)setControlView:(id)view; -- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame; -- (PSMTabBarCell *)lastVisibleTab; -- (NSUInteger)numberOfVisibleTabs; - -@end - -void CGContextCopyWindowCaptureContentsToRect(void *grafport, CGRect rect, NSInteger cid, NSInteger wid, NSInteger zero); -OSStatus CGSSetWindowTransform(NSInteger cid, NSInteger wid, CGAffineTransform transform); - -@interface NSApplication (CoreGraphicsUndocumented) -- (NSInteger)contextID; -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragAssistant.m b/Frameworks/PSMTabBar/PSMTabDragAssistant.m deleted file mode 100644 index 0bf424938..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragAssistant.m +++ /dev/null @@ -1,974 +0,0 @@ -// -// PSMTabDragAssistant.m -// PSMTabBarControl -// -// Created by John Pannell on 4/10/06. -// Copyright 2006 Positive Spin Media. All rights reserved. -// - -#import "PSMTabDragAssistant.h" -#import "PSMTabBarCell.h" -#import "PSMTabStyle.h" -#import "PSMTabDragWindowController.h" -#import "PSMOverflowPopUpButton.h" -#import "PSMRolloverButton.h" - -#define PI 3.1417 - -@interface PSMTabBarControl (Private) -- (void)update; -@end - -@interface PSMTabDragAssistant (Private) -- (NSImage *)_imageForViewOfCell:(PSMTabBarCell *)cell styleMask:(NSUInteger *)outMask; -- (NSImage *)_miniwindowImageOfWindow:(NSWindow *)window; -- (void)_expandWindow:(NSWindow *)window atPoint:(NSPoint)point; -- (void)_expandWindowTimerFired:(NSTimer *)timer; -@end - -@implementation PSMTabDragAssistant - -static PSMTabDragAssistant *sharedDragAssistant = nil; - -#pragma mark - -#pragma mark Creation/Destruction - -+ (PSMTabDragAssistant *)sharedDragAssistant -{ - if (!sharedDragAssistant) { - sharedDragAssistant = [[PSMTabDragAssistant alloc] init]; - } - - return sharedDragAssistant; -} - -- (instancetype)init -{ - if ( (self = [super init]) ) { - _sourceTabBar = nil; - _destinationTabBar = nil; - _participatingTabBars = [[NSMutableSet alloc] init]; - _draggedCell = nil; - _animationTimer = nil; - _sineCurveWidths = [[NSMutableArray alloc] initWithCapacity:kPSMTabDragAnimationSteps]; - _targetCell = nil; - _isDragging = NO; - } - - return self; -} - -#pragma mark - -#pragma mark Accessors - -- (PSMTabBarControl *)sourceTabBar -{ - return _sourceTabBar; -} - -- (void)setSourceTabBar:(PSMTabBarControl *)tabBar -{ - _sourceTabBar = tabBar; -} - -- (PSMTabBarControl *)destinationTabBar -{ - return _destinationTabBar; -} - -- (void)setDestinationTabBar:(PSMTabBarControl *)tabBar -{ - _destinationTabBar = tabBar; -} - -- (PSMTabBarCell *)draggedCell -{ - return _draggedCell; -} - -- (void)setDraggedCell:(PSMTabBarCell *)cell -{ - _draggedCell = cell; -} - -- (NSInteger)draggedCellIndex -{ - return _draggedCellIndex; -} - -- (void)setDraggedCellIndex:(NSInteger)value -{ - _draggedCellIndex = value; -} - -- (BOOL)isDragging -{ - return _isDragging; -} - -- (void)setIsDragging:(BOOL)value -{ - _isDragging = value; -} - -- (NSPoint)currentMouseLoc -{ - return _currentMouseLoc; -} - -- (void)setCurrentMouseLoc:(NSPoint)point -{ - _currentMouseLoc = point; -} - -- (PSMTabBarCell *)targetCell -{ - return _targetCell; -} - -- (void)setTargetCell:(PSMTabBarCell *)cell -{ - _targetCell = cell; -} - -#pragma mark - -#pragma mark Functionality - -- (void)startDraggingCell:(PSMTabBarCell *)cell fromTabBar:(PSMTabBarControl *)control withMouseDownEvent:(NSEvent *)event -{ - - // Ensure the window is frontmost - [[control window] makeKeyAndOrderFront:self]; - - [self setIsDragging:YES]; - [self setSourceTabBar:control]; - [self setDestinationTabBar:control]; - [_participatingTabBars addObject:control]; - [self setDraggedCell:cell]; - [self setDraggedCellIndex:[[control cells] indexOfObject:cell]]; - - NSRect cellFrame = [cell frame]; - - // Generate a list of widths for animation - NSInteger i; - CGFloat cellStepSize = ([control orientation] == PSMTabBarHorizontalOrientation) ? (cellFrame.size.width + 6) : (cellFrame.size.height + 1); - for (i = 0; i < kPSMTabDragAnimationSteps - 1; i++) { - NSInteger thisWidth = (NSInteger)(cellStepSize - ((cellStepSize/2.0) + ((sin((PI/2.0) + ((CGFloat)i/(CGFloat)kPSMTabDragAnimationSteps)*PI) * cellStepSize) / 2.0))); - [_sineCurveWidths addObject:[NSNumber numberWithInteger:thisWidth]]; - } - [_sineCurveWidths addObject:[NSNumber numberWithInteger:([control orientation] == PSMTabBarHorizontalOrientation) ? cellFrame.size.width : cellFrame.size.height]]; - - // hide UI buttons - [[control overflowPopUpButton] setHidden:YES]; - [[control addTabButton] setHidden:YES]; - - [[NSCursor closedHandCursor] set]; - - NSPasteboard *pboard; - if (@available(macOS 10.13, *)) { - pboard = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag]; - } else { - pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - } - NSImage *dragImage = [cell dragImage]; - [[cell indicator] removeFromSuperview]; - [self distributePlaceholdersInTabBar:control withDraggedCell:cell]; - - if ([control isFlipped]) { - cellFrame.origin.y += cellFrame.size.height; - } - [cell setHighlighted:NO]; - NSSize offset = NSZeroSize; - [pboard declareTypes:@[@"PSMTabBarControlItemPBType"] owner:nil]; - [pboard setString:[[NSNumber numberWithInteger:[[control cells] indexOfObject:cell]] stringValue] forType:@"PSMTabBarControlItemPBType"]; - _animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0/30.0) target:self selector:@selector(animateDrag:) userInfo:nil repeats:YES]; - - [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidBeginNotification object:nil]; - - //retain the control in case the drag operation causes the control to be released - - //TODO: jcs - fixing deprecated dragImage needs a DraggingItems and DragginSource. Beyond me. 2020-10-22 - if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - [[control delegate] tabView:[control tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil]) { - _currentTearOffStyle = [control tearOffStyle]; - _draggedTab = [[PSMTabDragWindowController alloc] initWithImage:dragImage styleMask:NSWindowStyleMaskBorderless tearOffStyle:_currentTearOffStyle initialAlpha:[control usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha]; - - cellFrame.origin.y -= cellFrame.size.height; - [control dragImage:[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] at:cellFrame.origin offset:offset event:event pasteboard:pboard source:control slideBack:NO]; - } else { - [control dragImage:dragImage at:cellFrame.origin offset:offset event:event pasteboard:pboard source:control slideBack:YES]; - } -} - -- (void)draggingEnteredTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc -{ - - // Bring the new tab window to the front - [[control window] makeKeyAndOrderFront:self]; - - if (_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![self destinationTabBar]) { - [_draggedTab switchImages]; - } - - // If this is not the starting drag bar... - if ([self sourceTabBar] != [self destinationTabBar] && control != [self destinationTabBar]) { - - // Add a single placeholder to the tab bar and tell the new tab bar to update. - // The placeholder is later removed by distributePlaceholdersInTabBar:. - PSMTabBarCell *pc = [[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control]; - [[control cells] addObject:pc]; - [control update]; - - // Deselect any currently selected tabs after the update - for (PSMTabBarCell *aCell in [control cells]) { - if ([aCell tabState] & PSMTab_SelectedMask) { - [aCell setState:NSOffState]; - [aCell setTabState:PSMTab_PositionMiddleMask]; - break; - } - } - } - - [self setDestinationTabBar:control]; - [self setCurrentMouseLoc:mouseLoc]; - - [_participatingTabBars addObject:control]; - - // Add placeholders if necessary - if ([[control cells] count] == 0 || ![[[control cells] objectAtIndex:0] isPlaceholder]) { - [self distributePlaceholdersInTabBar:control]; - } - - // hide UI buttons - [[control overflowPopUpButton] setHidden:YES]; - [[control addTabButton] setHidden:YES]; - - //tell the drag window to display only the header if there is one - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow && _draggedView) { - if (_fadeTimer) { - [_fadeTimer invalidate]; - } - - [[_draggedTab window] orderFront:nil]; - _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeOutDragWindow:) userInfo:nil repeats:YES]; - } -} - -- (void)draggingUpdatedInTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc -{ - if ([self destinationTabBar] != control) { - [self setDestinationTabBar:control]; - } - [self setCurrentMouseLoc:mouseLoc]; -} - -- (void)draggingExitedTabBar:(PSMTabBarControl *)control -{ - if ([[control delegate] respondsToSelector:@selector(tabView:shouldAllowTabViewItem:toLeaveTabBar:)] && - ![[control delegate] tabView:[control tabView] shouldAllowTabViewItem:[[self draggedCell] representedObject] toLeaveTabBar:control]) { - return; - } - - [self setDestinationTabBar:nil]; - [self setCurrentMouseLoc:NSMakePoint(-1.0f, -1.0f)]; - - if (_fadeTimer) { - [_fadeTimer invalidate]; - _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeInDragWindow:) userInfo:nil repeats:YES]; - } else if (_draggedTab) { - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { - //create a new floating drag window - if (!_draggedView) { - NSUInteger styleMask; - NSImage *viewImage = [self _imageForViewOfCell:[self draggedCell] styleMask:&styleMask]; - - _draggedView = [[PSMTabDragWindowController alloc] initWithImage:viewImage styleMask:styleMask tearOffStyle:PSMTabBarTearOffAlphaWindow initialAlpha:[control usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha]; - [[_draggedView window] setAlphaValue:0.0f]; - - // Inform the delegate a new drag window was created to allow any changes - if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabViewDragWindowCreated:)]) { - [[control delegate] tabViewDragWindowCreated:[_draggedView window]]; - } - } - - NSPoint targetPoint = [[_draggedTab window] frame].origin; - targetPoint.y += _dragWindowOffset.height; - [[_draggedView window] setFrameTopLeftPoint:targetPoint]; - [[_draggedView window] orderWindow:NSWindowBelow relativeTo:[[_draggedTab window] windowNumber]]; - - } else if (_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![_draggedTab alternateImage]) { - NSImage *image; - NSSize imageSize; - NSUInteger mask; //we don't need this but we can't pass nil in for the style mask, as some delegate implementations will crash - - if ( !(image = [self _miniwindowImageOfWindow:[control window]]) ) { - image = [[self _imageForViewOfCell:[self draggedCell] styleMask:&mask] copy]; - } - - imageSize = [image size]; - - if (imageSize.width > imageSize.height) { - [image setSize:NSMakeSize(125, 125 * (imageSize.height / imageSize.width))]; - } else { - [image setSize:NSMakeSize(125 * (imageSize.width / imageSize.height), 125)]; - } - - [_draggedTab setAlternateImage:image]; - } - - //set the window's alpha mask to zero if the last tab is being dragged - //don't fade out the old window if the delegate doesn't respond to the new tab bar method, just to be safe - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1 && [self sourceTabBar] == control && - [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) { - [[[self sourceTabBar] window] setAlphaValue:0.0f]; - [[[self sourceTabBar] window] setIgnoresMouseEvents:YES]; - - if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { - [[_draggedView window] setAlphaValue:kPSMTabDragWindowAlpha]; - } else { - [_draggedTab switchImages]; - _centersDragWindows = YES; - } - } else { - if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { - _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeInDragWindow:) userInfo:nil repeats:YES]; - } else { - [_draggedTab switchImages]; - _centersDragWindows = YES; - } - } - } -} - -- (void)performDragOperation -{ - // move cell - NSUInteger destinationIndex = [[[self destinationTabBar] cells] indexOfObject:[self targetCell]]; - - //there is the slight possibility of the targetCell now being set properly, so avoid errors - if (destinationIndex >= [[[self destinationTabBar] cells] count]) { - destinationIndex = [[[self destinationTabBar] cells] count] - 1; - } - - [[[self destinationTabBar] cells] replaceObjectAtIndex:destinationIndex withObject:[self draggedCell]]; - [[self draggedCell] setCustomControlView:[self destinationTabBar]]; - - // move actual NSTabViewItem - if ([self sourceTabBar] != [self destinationTabBar]) { - - //remove the tracking rects and bindings registered on the old tab - [[self sourceTabBar] removeTrackingRect:[[self draggedCell] closeButtonTrackingTag]]; - [[self sourceTabBar] removeTrackingRect:[[self draggedCell] cellTrackingTag]]; - [[self sourceTabBar] removeTabForCell:[self draggedCell]]; - - NSUInteger i; - NSInteger insertIndex; - NSArray *cells = [[self destinationTabBar] cells]; - - //find the index of where the dragged cell was just dropped - for (i = 0, insertIndex = 0; (i < [cells count]) && ([cells objectAtIndex:i] != [self draggedCell]); i++, insertIndex++) { - if ([[cells objectAtIndex:i] isPlaceholder]) { - insertIndex--; - } - } - - [[[self sourceTabBar] tabView] removeTabViewItem:[[self draggedCell] representedObject]]; - [[[self destinationTabBar] tabView] insertTabViewItem:[[self draggedCell] representedObject] atIndex:insertIndex]; - - //rebind the cell to the new control - [[self destinationTabBar] bindPropertiesForCell:[self draggedCell] andTabViewItem:[[self draggedCell] representedObject]]; - - //select the newly moved item in the destination tab view - [[[self destinationTabBar] tabView] selectTabViewItem:[[self draggedCell] representedObject]]; - } else { - //have to do this before checking the index of a cell otherwise placeholders will be counted - [self removeAllPlaceholdersFromTabBar:[self sourceTabBar]]; - - //rearrange the tab view items - NSTabView *tabView = [[self sourceTabBar] tabView]; - NSTabViewItem *item = [[self draggedCell] representedObject]; - BOOL reselect = ([tabView selectedTabViewItem] == item); - NSUInteger anIndex; - NSArray *cells = [[self sourceTabBar] cells]; - - //find the index of where the dragged cell was just dropped - for (anIndex = 0; anIndex < [cells count] && [cells objectAtIndex:anIndex] != [self draggedCell]; anIndex++); - - //temporarily disable the delegate in order to move the tab to a different index - id tempDelegate = [tabView delegate]; - [tabView setDelegate:nil]; - [tabView removeTabViewItem:item]; - [tabView insertTabViewItem:item atIndex:anIndex]; - if (reselect) { - [tabView selectTabViewItem:item]; - } - [tabView setDelegate:tempDelegate]; - } - - if (([self sourceTabBar] != [self destinationTabBar] || (NSInteger)[[[self sourceTabBar] cells] indexOfObject:[self draggedCell]] != _draggedCellIndex) && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { - [[[self sourceTabBar] delegate] tabView:[[self sourceTabBar] tabView] didDropTabViewItem:[[self draggedCell] representedObject] inTabBar:[self destinationTabBar]]; - } - - [self finishDrag]; - - [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidEndNotification object:nil]; -} - -- (void)draggedImageEndedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - if ([self isDragging]) { // means there was not a successful drop (performDragOperation) - id sourceDelegate = [[self sourceTabBar] delegate]; - - // Extract the menu bar rect - NSScreen *menuBarScreen = [[NSScreen screens] objectAtIndex:0]; - NSRect menuBarRect = [menuBarScreen frame]; - menuBarRect.origin.y = menuBarRect.size.height; - menuBarRect.size.height = 22; - - // Split off the dragged tab into a new window. - // Do this if there's no destination tab bar, the delegate approves it, and the delegate supports it - and - // not if the drag ended in the menu bar (which acts as a cancel) - if ([self destinationTabBar] == nil - && sourceDelegate && [sourceDelegate respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - [sourceDelegate tabView:[[self sourceTabBar] tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil] - && [sourceDelegate respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)] - && !NSPointInRect(aPoint, menuBarRect)) - { - PSMTabBarControl *control = [sourceDelegate tabView:[[self sourceTabBar] tabView] newTabBarForDraggedTabViewItem:[[self draggedCell] representedObject] atPoint:aPoint]; - - if (control) { - //add the dragged tab to the new window - [[control cells] insertObject:[self draggedCell] atIndex:0]; - - //remove the tracking rects and bindings registered on the old tab - [[self sourceTabBar] removeTrackingRect:[[self draggedCell] closeButtonTrackingTag]]; - [[self sourceTabBar] removeTrackingRect:[[self draggedCell] cellTrackingTag]]; - [[self sourceTabBar] removeTabForCell:[self draggedCell]]; - - //rebind the cell to the new control - [control bindPropertiesForCell:[self draggedCell] andTabViewItem:[[self draggedCell] representedObject]]; - - [[self draggedCell] setCustomControlView:control]; - - [[[self sourceTabBar] tabView] removeTabViewItem:[[self draggedCell] representedObject]]; - - [[control tabView] addTabViewItem:[[self draggedCell] representedObject]]; - [control update]; //make sure the new tab is set in the correct position - - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { - - // Grab the window frame, and show - which moves it fully onto screen - before restoring - NSRect draggedWindowFrame = [[control window] frame]; - [[control window] makeKeyAndOrderFront:nil]; - [[control window] setFrame:draggedWindowFrame display:YES]; - } else { - //center the window over where we ended dragging - [self _expandWindow:[control window] atPoint:[NSEvent mouseLocation]]; - } - - if ([sourceDelegate respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { - [sourceDelegate tabView:[[self sourceTabBar] tabView] didDropTabViewItem:[[self draggedCell] representedObject] inTabBar:control]; - } - } else { - NSLog(@"Delegate returned no control to add to."); - [[[self sourceTabBar] cells] insertObject:[self draggedCell] atIndex:[self draggedCellIndex]]; - } - - } else { - - // put cell back - [[[self sourceTabBar] cells] insertObject:[self draggedCell] atIndex:[self draggedCellIndex]]; - [[[self sourceTabBar] window] makeKeyAndOrderFront:self]; - - // Restore the window alpha if appropriate - if ([[[self sourceTabBar] tabView] numberOfTabViewItems]) { - [[[self sourceTabBar] window] setAlphaValue:1.0f]; - } - } - - [self finishDrag]; - - [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidEndNotification object:nil]; - } -} - -- (void)finishDrag -{ - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 0 && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:closeWindowForLastTabViewItem:)]) { - [[[self sourceTabBar] delegate] tabView:[[self sourceTabBar] tabView] closeWindowForLastTabViewItem:[[self draggedCell] representedObject]]; - } - - if (_draggedTab) { - [[_draggedTab window] orderOut:nil]; - _draggedTab = nil; - } - - if (_draggedView) { - [[_draggedView window] orderOut:nil]; - _draggedView = nil; - } - - _centersDragWindows = NO; - - [_animationTimer invalidate]; - _animationTimer = nil; - - [self removeAllPlaceholdersFromTabBar:[self sourceTabBar]]; - [self setSourceTabBar:nil]; - [self setDestinationTabBar:nil]; - - NSEnumerator *e = [_participatingTabBars objectEnumerator]; - PSMTabBarControl *tabBar; - while ( (tabBar = [e nextObject]) ) { - [self removeAllPlaceholdersFromTabBar:tabBar]; - } - [_participatingTabBars removeAllObjects]; - - [self setDraggedCell:nil]; - [_sineCurveWidths removeAllObjects]; - [self setTargetCell:nil]; - [self setIsDragging:NO]; -} - -- (void)draggingBeganAt:(NSPoint)aPoint -{ - if (_draggedTab) { - [[_draggedTab window] setFrameTopLeftPoint:aPoint]; - [[_draggedTab window] orderFront:nil]; - - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1) { - [self draggingExitedTabBar:[self sourceTabBar]]; - if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { - [[_draggedTab window] setAlphaValue:0.0f]; - } - } - } -} - -- (void)draggingMovedTo:(NSPoint)aPoint -{ - if (_draggedTab) { - if (_centersDragWindows) { - if ([_draggedTab isAnimating]) { - return; - } - - //Ignore aPoint, as it seems to give wacky values - NSRect frame = [[_draggedTab window] frame]; - frame.origin = [NSEvent mouseLocation]; - frame.origin.x -= frame.size.width / 2; - frame.origin.y -= frame.size.height / 2; - [[_draggedTab window] setFrame:frame display:NO]; - } else { - - // If there is a destination tab bar set to snapping, snap the tab to it. - if ([self destinationTabBar] - && [[self destinationTabBar] usesSafariStyleDragging] - && [[self destinationTabBar] orientation] == PSMTabBarHorizontalOrientation) - { - NSRect windowFrame = [[[self destinationTabBar] window] frame]; - NSPoint dragPointInWindow = [[self destinationTabBar] convertPoint:aPoint fromView:nil]; - - // Vertical snapping - aPoint.y += windowFrame.origin.y + dragPointInWindow.y; - - // Horizontal constraining/snapping - if (dragPointInWindow.x - windowFrame.origin.x < 0) aPoint.x = windowFrame.origin.x; - if (dragPointInWindow.x - windowFrame.origin.x + [[_draggedTab window] frame].size.width > windowFrame.size.width) aPoint.x = windowFrame.origin.x + windowFrame.size.width - [[_draggedTab window] frame].size.width; - } - [[_draggedTab window] setFrameTopLeftPoint:aPoint]; - } - - if (_draggedView) { - //move the view representation with the tab - //the relative position of the dragged view window will be different - //depending on the position of the tab bar relative to the controlled tab view - - aPoint.y -= [[_draggedTab window] frame].size.height; - aPoint.x -= _dragWindowOffset.width; - aPoint.y += _dragWindowOffset.height; - [[_draggedView window] setFrameTopLeftPoint:aPoint]; - } - } -} - -- (void)fadeInDragWindow:(NSTimer *)timer -{ - CGFloat value = [[_draggedView window] alphaValue]; - if (value >= kPSMTabDragWindowAlpha || _draggedTab == nil) { - [timer invalidate]; - _fadeTimer = nil; - } else { - [[_draggedTab window] setAlphaValue:[[_draggedTab window] alphaValue] - kPSMTabDragAlphaInterval]; - [[_draggedView window] setAlphaValue:value + kPSMTabDragAlphaInterval]; - } -} - -- (void)fadeOutDragWindow:(NSTimer *)timer -{ - CGFloat value = [[_draggedView window] alphaValue]; - NSWindow *tabWindow = [_draggedTab window], *viewWindow = [_draggedView window]; - float tabWindowAlphaValue = [[self destinationTabBar] usesSafariStyleDragging]?1:kPSMTabDragWindowAlpha; - - if (value <= 0.0) { - [viewWindow setAlphaValue:0.0f]; - [tabWindow setAlphaValue:tabWindowAlphaValue]; - - [timer invalidate]; - _fadeTimer = nil; - } else { - if ([tabWindow alphaValue] < tabWindowAlphaValue) { - [tabWindow setAlphaValue:[tabWindow alphaValue] + kPSMTabDragAlphaInterval]; - } - [viewWindow setAlphaValue:value - kPSMTabDragAlphaInterval]; - } -} - -#pragma mark - -#pragma mark Private - -- (NSImage *)_imageForViewOfCell:(PSMTabBarCell *)cell styleMask:(NSUInteger *)outMask -{ - PSMTabBarControl *control = (PSMTabBarControl *)[cell controlView]; - NSImage *viewImage = nil; - - if (outMask) { - *outMask = NSWindowStyleMaskBorderless; - } - - if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:imageForTabViewItem:offset:styleMask:)]) { - //get a custom image representation of the view to drag from the delegate - NSImage *tabImage = [_draggedTab image]; - NSPoint drawPoint; - NSRect drawRect; - _dragWindowOffset = NSZeroSize; - viewImage = [[control delegate] tabView:[control tabView] imageForTabViewItem:[cell representedObject] offset:&_dragWindowOffset styleMask:outMask]; - [viewImage lockFocus]; - - //draw the tab into the returned window, that way we don't have two windows being dragged (this assumes the tab will be on the window) - drawPoint = NSMakePoint(_dragWindowOffset.width, [viewImage size].height - _dragWindowOffset.height); - - if ([control orientation] == PSMTabBarHorizontalOrientation) { - drawPoint.y += [[control style] tabCellHeight] - [tabImage size].height; - _dragWindowOffset.height -= [[control style] tabCellHeight] - [tabImage size].height; - } else { - drawPoint.x += [control frame].size.width - [tabImage size].width; - } - drawRect = NSMakeRect(drawPoint.x, drawPoint.y, [tabImage size].width, [tabImage size].height); - - [tabImage drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0f respectFlipped:YES hints:nil]; - - [viewImage unlockFocus]; - } else { - //the delegate doesn't give a custom image, so use an image of the view - NSView *tabView = [[cell representedObject] view]; - viewImage = [[NSImage alloc] initWithSize:[tabView frame].size]; - [viewImage lockFocus]; - [tabView drawRect:[tabView bounds]]; - [viewImage unlockFocus]; - } - - if (outMask && (*outMask | NSWindowStyleMaskBorderless)) { - _dragWindowOffset.height += 22; - } - - return viewImage; -} - -- (NSImage *)_miniwindowImageOfWindow:(NSWindow *)window -{ - NSRect rect = [window frame]; - NSImage *image = [[NSImage alloc] initWithSize:rect.size]; - [image lockFocus]; - rect.origin = NSZeroPoint; - CGContextCopyWindowCaptureContentsToRect([[NSGraphicsContext currentContext] graphicsPort], *(CGRect *)&rect, [NSApp contextID], [window windowNumber], 0); - [image unlockFocus]; - - return image; -} - -- (void)_expandWindow:(NSWindow *)window atPoint:(NSPoint)point -{ - NSRect frame = [window frame]; - [window setFrameTopLeftPoint:NSMakePoint(point.x - frame.size.width / 2, point.y + frame.size.height / 2)]; - [window setAlphaValue:0.0f]; - [window makeKeyAndOrderFront:nil]; - - NSAnimation *animation = [[NSAnimation alloc] initWithDuration:0.25 animationCurve:NSAnimationEaseInOut]; - [animation setAnimationBlockingMode:NSAnimationNonblocking]; - [animation setCurrentProgress:0.1f]; - [animation startAnimation]; - NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(_expandWindowTimerFired:) userInfo:[NSDictionary dictionaryWithObjectsAndKeys:window, @"Window", animation, @"Animation", nil] repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode]; -} - -- (void)_expandWindowTimerFired:(NSTimer *)timer -{ - NSWindow *window = [[timer userInfo] objectForKey:@"Window"]; - NSAnimation *animation = [[timer userInfo] objectForKey:@"Animation"]; - CGAffineTransform transform; - NSPoint translation; - NSRect winFrame = [window frame]; - - translation.x = (winFrame.size.width / 2.0f); - translation.y = (winFrame.size.height / 2.0f); - transform = CGAffineTransformMakeTranslation(translation.x, translation.y); - transform = CGAffineTransformScale(transform, 1.0f / [animation currentValue], 1.0f / [animation currentValue]); - transform = CGAffineTransformTranslate(transform, -translation.x, -translation.y); - - translation.x = -winFrame.origin.x; - translation.y = winFrame.origin.y + winFrame.size.height - [[NSScreen mainScreen] frame].size.height; - - transform = CGAffineTransformTranslate(transform, translation.x, translation.y); - - CGSSetWindowTransform([NSApp contextID], [window windowNumber], transform); - - [window setAlphaValue:[animation currentValue]]; - - if (![animation isAnimating]) { - [timer invalidate]; - } -} - -#pragma mark - -#pragma mark Animation - -- (void)animateDrag:(NSTimer *)timer -{ - NSEnumerator *e = [[_participatingTabBars copy] objectEnumerator]; - PSMTabBarControl *tabBar; - while ( (tabBar = [e nextObject]) ) { - [self calculateDragAnimationForTabBar:tabBar]; - [[NSRunLoop currentRunLoop] performSelector:@selector(display) target:tabBar argument:nil order:1 modes:@[@"NSEventTrackingRunLoopMode", @"NSDefaultRunLoopMode"]]; - } -} - -- (void)calculateDragAnimationForTabBar:(PSMTabBarControl *)control -{ - BOOL removeFlag = YES; - NSMutableArray *cells = [control cells]; - NSInteger i, cellCount = [cells count]; - CGFloat position = [control orientation] == PSMTabBarHorizontalOrientation ? [[control style] leftMarginForTabBarControl] : [[control style] topMarginForTabBarControl]; - - if ([self destinationTabBar] == control) { - removeFlag = NO; - - // Determine the location of the point to use. - NSPoint targetPoint; - if ([control usesSafariStyleDragging]) { - NSRect draggedTabWindowFrame = [[_draggedTab window] contentRectForFrameRect:[[_draggedTab window] frame]]; - NSRect controlWindowFrame = [[control window] contentRectForFrameRect:[[control window] frame]]; - NSPoint tabTopLeftInWindowCoords = NSMakePoint(draggedTabWindowFrame.origin.x - controlWindowFrame.origin.x, controlWindowFrame.origin.y + (2*controlWindowFrame.size.height) - draggedTabWindowFrame.origin.y); - targetPoint = [control convertPoint:tabTopLeftInWindowCoords fromView:nil]; - targetPoint.x += (draggedTabWindowFrame.size.width / 2.0f); - targetPoint.y = 0 - (draggedTabWindowFrame.size.height / 2.0f) - targetPoint.y; - } else { - targetPoint = [self currentMouseLoc]; - } - - if (targetPoint.x < [[control style] leftMarginForTabBarControl]) { - [self setTargetCell:[cells objectAtIndex:0]]; - } else { - - // Identify which cell the mouse is over - NSRect overCellRect; - PSMTabBarCell *overCell = [control cellForPoint:targetPoint cellFrame:&overCellRect]; - if (overCell) { - - // Mouse is among cells - placeholder - if ([overCell isPlaceholder]) { - [self setTargetCell:overCell]; - - // Non-placeholder cells - horizontal orientation - } else if ([control orientation] == PSMTabBarHorizontalOrientation) { - - // Handle Safari-style dragging - if ([control usesSafariStyleDragging]) { - - // Determine the index of the tab the dragged tab is over - NSUInteger overCellIndex = [cells indexOfObject:overCell]; - - // Determine the index of the current target - NSUInteger currentTargetCellIndex = _targetCell?[cells indexOfObject:_targetCell]:NSUIntegerMax; - - // Ensure that drag changes aren't as a result of an animation - NSInteger currentCellStep = [[cells objectAtIndex:(overCellIndex - 1)] currentStep]; - if (!currentCellStep || currentCellStep == kPSMTabDragAnimationSteps - 1) { - - // Center of the tab is past the edge of the tab to the left - if (targetPoint.x < (overCellRect.origin.x + overCellRect.size.width) - && currentTargetCellIndex > overCellIndex) - { - [self setTargetCell:[cells objectAtIndex:(overCellIndex - 1)]]; - - // Center of the tab is past the edge of the tab to the right - } else if (targetPoint.x > overCellRect.origin.x) { - [self setTargetCell:[cells objectAtIndex:(overCellIndex + 1)]]; - } - } - - // Handle old-style dragging based on mouse position - } else { - - // Mouse is over the left side of the cell - if (targetPoint.x < (overCellRect.origin.x + (overCellRect.size.width / 2.0))) { - [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]]; - - // Otherwise the mouse is over the right side of the cell - } else { - [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] + 1)]]; - } - } - } else { - // non-placeholders - vertical orientation - if (targetPoint.y < (overCellRect.origin.y + (overCellRect.size.height / 2.0))) { - // mouse on top of cell - [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]]; - } else { - // mouse on bottom of cell - [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] + 1)]]; - } - } - } else { - // out at end - must find proper cell (could be more in overflow menu) - [self setTargetCell:[control lastVisibleTab]]; - } - } - } else { - [self setTargetCell:nil]; - } - - for (i = 0; i < cellCount; i++) { - PSMTabBarCell *cell = [cells objectAtIndex:i]; - NSRect newRect = [cell frame]; - if (![cell isInOverflowMenu]) { - if ([cell isPlaceholder]) { - if (cell == [self targetCell]) { - [cell setCurrentStep:([cell currentStep] + 1)]; - } else { - [cell setCurrentStep:([cell currentStep] - 1)]; - if ([cell currentStep] > 0) { - removeFlag = NO; - } - } - - if ([control orientation] == PSMTabBarHorizontalOrientation) { - newRect.size.width = [[_sineCurveWidths objectAtIndex:[cell currentStep]] integerValue]; - } else { - newRect.size.height = [[_sineCurveWidths objectAtIndex:[cell currentStep]] integerValue]; - } - } - } else { - break; - } - - if ([control orientation] == PSMTabBarHorizontalOrientation) { - newRect.origin.x = position; - position += newRect.size.width; - } else { - newRect.origin.y = position; - position += newRect.size.height; - } - [cell setFrame:newRect]; - if ([cell indicator]) { - [[cell indicator] setFrame:[[control style] indicatorRectForTabCell:cell]]; - } - } - if (removeFlag) { - [_participatingTabBars removeObject:control]; - [self removeAllPlaceholdersFromTabBar:control]; - } -} - -#pragma mark - -#pragma mark Placeholders - -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control withDraggedCell:(PSMTabBarCell *)cell -{ - // called upon first drag - must distribute placeholders - [self distributePlaceholdersInTabBar:control]; - - NSMutableArray *cells = [control cells]; - - // replace dragged cell with a placeholder, and clean up surrounding cells - NSInteger cellIndex = [cells indexOfObject:cell]; - PSMTabBarCell *pc = [[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:YES inControlView:control]; - [cells replaceObjectAtIndex:cellIndex withObject:pc]; - [cells removeObjectAtIndex:(cellIndex + 1)]; - [cells removeObjectAtIndex:(cellIndex - 1)]; - - if (cellIndex - 2 >= 0) { - pc = [cells objectAtIndex:cellIndex - 2]; - [pc setTabState:~[pc tabState] & PSMTab_RightIsSelectedMask]; - } -} - -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control -{ - NSUInteger i, numVisibleTabs = [control numberOfVisibleTabs]; - for (i = 0; i < numVisibleTabs; i++) { - PSMTabBarCell *pc = [[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control]; - [[control cells] insertObject:pc atIndex:(2 * i)]; - } - - PSMTabBarCell *pc = [[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control]; - if ([[control cells] count] > (2 * numVisibleTabs)) { - [[control cells] insertObject:pc atIndex:(2 * numVisibleTabs)]; - } else { - [[control cells] addObject:pc]; - } -} - -- (void)removeAllPlaceholdersFromTabBar:(PSMTabBarControl *)control -{ - NSInteger i, cellCount = [[control cells] count]; - for (i = (cellCount - 1); i >= 0; i--) { - PSMTabBarCell *cell = [[control cells] objectAtIndex:i]; - if ([cell isPlaceholder]) { - [NSObject cancelPreviousPerformRequestsWithTarget:cell]; - [control removeTabForCell:cell]; - } - } - // redraw - [control update]; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)aCoder { - //[super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_sourceTabBar forKey:@"sourceTabBar"]; - [aCoder encodeObject:_destinationTabBar forKey:@"destinationTabBar"]; - [aCoder encodeObject:_participatingTabBars forKey:@"participatingTabBars"]; - [aCoder encodeObject:_draggedCell forKey:@"draggedCell"]; - [aCoder encodeInteger:_draggedCellIndex forKey:@"draggedCellIndex"]; - [aCoder encodeBool:_isDragging forKey:@"isDragging"]; - [aCoder encodeObject:_animationTimer forKey:@"animationTimer"]; - [aCoder encodeObject:_sineCurveWidths forKey:@"sineCurveWidths"]; - [aCoder encodePoint:_currentMouseLoc forKey:@"currentMouseLoc"]; - [aCoder encodeObject:_targetCell forKey:@"targetCell"]; - } -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - //self = [super initWithCoder:aDecoder]; - //if (self) { - if ([aDecoder allowsKeyedCoding]) { - _sourceTabBar = [aDecoder decodeObjectForKey:@"sourceTabBar"]; - _destinationTabBar = [aDecoder decodeObjectForKey:@"destinationTabBar"]; - _participatingTabBars = [aDecoder decodeObjectForKey:@"participatingTabBars"]; - _draggedCell = [aDecoder decodeObjectForKey:@"draggedCell"]; - _draggedCellIndex = [aDecoder decodeIntegerForKey:@"draggedCellIndex"]; - _isDragging = [aDecoder decodeBoolForKey:@"isDragging"]; - _animationTimer = [aDecoder decodeObjectForKey:@"animationTimer"]; - _sineCurveWidths = [aDecoder decodeObjectForKey:@"sineCurveWidths"]; - _currentMouseLoc = [aDecoder decodePointForKey:@"currentMouseLoc"]; - _targetCell = [aDecoder decodeObjectForKey:@"targetCell"]; - } - //} - return self; -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragView.h b/Frameworks/PSMTabBar/PSMTabDragView.h deleted file mode 100644 index bdf73304b..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragView.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PSMTabDragView.h -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/17/07. -// Copyright 2007 Kent Sutherland. All rights reserved. -// - -#import - -@interface PSMTabDragView : NSView { - NSImage *_image, *_alternateImage; - CGFloat _alpha; -} -- (void)setFadeValue:(CGFloat)value; -- (NSImage *)image; -- (void)setImage:(NSImage *)image; -- (NSImage *)alternateImage; -- (void)setAlternateImage:(NSImage *)image; -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragView.m b/Frameworks/PSMTabBar/PSMTabDragView.m deleted file mode 100644 index a044de656..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragView.m +++ /dev/null @@ -1,60 +0,0 @@ -// -// PSMTabDragView.m -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/17/07. -// Copyright 2007 Kent Sutherland. All rights reserved. -// - -#import "PSMTabDragView.h" - -@implementation PSMTabDragView - -- (instancetype)initWithFrame:(NSRect)frame { - if ( (self = [super initWithFrame:frame]) ) { - _alpha = 1.0f; - } - return self; -} - -- (void)drawRect:(NSRect)rect { - //1.0 fade means show the primary image - //0.0 fade means show the secondary image - CGFloat primaryAlpha = _alpha + 0.001f, alternateAlpha = 1.001f - _alpha; - NSRect srcRect; - srcRect.origin = NSZeroPoint; - srcRect.size = [_image size]; - - [_image drawInRect:[self bounds] fromRect:srcRect operation:NSCompositingOperationSourceOver fraction:primaryAlpha]; - - srcRect.size = [_alternateImage size]; - - [_alternateImage drawInRect:[self bounds] fromRect:srcRect operation:NSCompositingOperationSourceOver fraction:alternateAlpha]; -} - -- (void)setFadeValue:(CGFloat)value -{ - _alpha = value; -} - -- (NSImage *)image -{ - return _image; -} - -- (void)setImage:(NSImage *)image -{ - _image = image; -} - -- (NSImage *)alternateImage -{ - return _alternateImage; -} - -- (void)setAlternateImage:(NSImage *)image -{ - _alternateImage = image; -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragWindow.h b/Frameworks/PSMTabBar/PSMTabDragWindow.h deleted file mode 100644 index a14df53e1..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragWindow.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PSMTabDragWindow.h -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/1/06. -// Copyright 2006 Kent Sutherland. All rights reserved. -// - -#import - -@class PSMTabDragView; - -@interface PSMTabDragWindow : NSWindow { - PSMTabDragView *_dragView; -} -+ (PSMTabDragWindow *)dragWindowWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask; - -- (instancetype)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask; -- (PSMTabDragView *)dragView; -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragWindow.m b/Frameworks/PSMTabBar/PSMTabDragWindow.m deleted file mode 100644 index 8413d5802..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragWindow.m +++ /dev/null @@ -1,52 +0,0 @@ -// -// PSMTabDragWindow.m -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/1/06. -// Copyright 2006 Kent Sutherland. All rights reserved. -// - -#import "PSMTabDragWindow.h" -#import "PSMTabDragView.h" - -@implementation PSMTabDragWindow - -+ (PSMTabDragWindow *)dragWindowWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask -{ - return [[PSMTabDragWindow alloc] initWithImage:image styleMask:styleMask]; -} - -- (instancetype)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask -{ - NSSize size = [image size]; - - if ( (self = [super initWithContentRect:NSMakeRect(0, 0, size.width, size.height) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]) ) { - _dragView = [[PSMTabDragView alloc] initWithFrame:NSMakeRect(0, 0, size.width, size.height)]; - [self setContentView:_dragView]; - [self setLevel:NSStatusWindowLevel]; - [self setIgnoresMouseEvents:YES]; - [self setOpaque:NO]; - [self setBackgroundColor:[NSColor clearColor]]; - - [_dragView setImage:image]; - - //Set the size of the window to be the exact size of the drag image - NSRect windowFrame = [self frame]; - windowFrame.origin.y += windowFrame.size.height - size.height; - windowFrame.size = size; - - if (styleMask | NSWindowStyleMaskBorderless) { - windowFrame.size.height += 22; - } - - [self setFrame:windowFrame display:YES]; - } - return self; -} - -- (PSMTabDragView *)dragView -{ - return _dragView; -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragWindowController.h b/Frameworks/PSMTabBar/PSMTabDragWindowController.h deleted file mode 100644 index c6e6c7830..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragWindowController.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// PSMTabDragWindowController.h -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/18/07. -// Copyright 2007 Kent Sutherland. All rights reserved. -// - -#import -#import "PSMTabBarControl.h" - -#define kPSMTabDragWindowAlpha 0.75f -#define kPSMTabDragAlphaInterval 0.15f - -@class PSMTabDragView; - -@interface PSMTabDragWindowController : NSWindowController { - PSMTabBarTearOffStyle _tearOffStyle; - PSMTabDragView *_view; - NSAnimation *_animation; - NSTimer *_timer; - - BOOL _showingAlternate; - NSRect _originalWindowFrame; -} -- (instancetype)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle initialAlpha:(CGFloat)initialAlpha; - -- (NSImage *)image; -- (NSImage *)alternateImage; -- (void)setAlternateImage:(NSImage *)image; -- (BOOL)isAnimating; -- (void)switchImages; -- (void)animateTimer:(NSTimer *)timer; -@end diff --git a/Frameworks/PSMTabBar/PSMTabDragWindowController.m b/Frameworks/PSMTabBar/PSMTabDragWindowController.m deleted file mode 100644 index 9081f83b5..000000000 --- a/Frameworks/PSMTabBar/PSMTabDragWindowController.m +++ /dev/null @@ -1,111 +0,0 @@ -// -// PSMTabDragWindowController.m -// PSMTabBarControl -// -// Created by Kent Sutherland on 6/18/07. -// Copyright 2007 Kent Sutherland. All rights reserved. -// - -#import "PSMTabDragWindowController.h" -#import "PSMTabDragWindow.h" -#import "PSMTabDragView.h" - -@implementation PSMTabDragWindowController - -- (instancetype)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle initialAlpha:(CGFloat)initialAlpha -{ - PSMTabDragWindow *window = [PSMTabDragWindow dragWindowWithImage:image styleMask:styleMask]; - if ( (self = [super initWithWindow:window]) ) { - _view = [window dragView]; - _tearOffStyle = tearOffStyle; - - if (tearOffStyle == PSMTabBarTearOffMiniwindow) { - [window setBackgroundColor:[NSColor clearColor]]; - [window setHasShadow:YES]; - } - - [window setAlphaValue:initialAlpha]; - } - return self; -} - -- (void)dealloc -{ - if (_timer) { - [_timer invalidate]; - } -} - -- (NSImage *)image -{ - return [_view image]; -} - -- (NSImage *)alternateImage -{ - return [_view alternateImage]; -} - -- (void)setAlternateImage:(NSImage *)image -{ - [_view setAlternateImage:image]; -} - -- (BOOL)isAnimating -{ - return _animation != nil; -} - -- (void)switchImages -{ - if (_tearOffStyle != PSMTabBarTearOffMiniwindow || ![_view alternateImage]) { - return; - } - - CGFloat progress = 0; - _showingAlternate = !_showingAlternate; - - if (_animation) { - //An animation already exists, get the current progress - progress = 1.0f - [_animation currentProgress]; - [_animation stopAnimation]; - } - - //begin animating - _animation = [[NSAnimation alloc] initWithDuration:0.25 animationCurve:NSAnimationEaseInOut]; - [_animation setAnimationBlockingMode:NSAnimationNonblocking]; - [_animation setCurrentProgress:progress]; - [_animation startAnimation]; - - _originalWindowFrame = [[self window] frame]; - - if (_timer) { - [_timer invalidate]; - } - _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f / 30.0f target:self selector:@selector(animateTimer:) userInfo:nil repeats:YES]; -} - -- (void)animateTimer:(NSTimer *)timer -{ - NSRect frame = _originalWindowFrame; - NSImage *currentImage = _showingAlternate ? [_view alternateImage] : [_view image]; - NSSize size = [currentImage size]; - NSPoint mousePoint = [NSEvent mouseLocation]; - CGFloat animationValue = [_animation currentValue]; - - frame.size.width = _originalWindowFrame.size.width + (size.width - _originalWindowFrame.size.width) * animationValue; - frame.size.height = _originalWindowFrame.size.height + (size.height - _originalWindowFrame.size.height) * animationValue; - frame.origin.x = mousePoint.x - (frame.size.width / 2); - frame.origin.y = mousePoint.y - (frame.size.height / 2); - - [_view setFadeValue:_showingAlternate ? 1.0f - animationValue : animationValue]; - [[self window] setFrame:frame display:YES]; - - if (![_animation isAnimating]) { - _animation = nil; - [timer invalidate]; - _timer = nil; - } -} - -@end diff --git a/Frameworks/PSMTabBar/PSMTabStyle.h b/Frameworks/PSMTabBar/PSMTabStyle.h deleted file mode 100644 index 7238bb9e1..000000000 --- a/Frameworks/PSMTabBar/PSMTabStyle.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// PSMTabStyle.h -// PSMTabBarControl -// -// Created by John Pannell on 2/17/06. -// Copyright 2006 Positive Spin Media. All rights reserved. -// - -/* - * Protocol to be observed by all style delegate objects. - * These objects handle the drawing responsibilities for PSMTabBarCell; once the control has been assigned a style, the background and cells draw consistent with that style. - * Design pattern and implementation by David Smith, Seth Willits, and Chris Forsythe, all touch up and errors by John P. :-) - */ - -#import "PSMTabBarCell.h" -#import "PSMTabBarControl.h" - -@protocol PSMTabStyle - -// identity -- (NSString *)name; - -// control specific parameters -- (CGFloat)leftMarginForTabBarControl; -- (CGFloat)rightMarginForTabBarControl; -- (CGFloat)topMarginForTabBarControl; -- (void)setOrientation:(PSMTabBarOrientation)value; - -// add tab button -- (NSImage *)addTabButtonImage; - -// cell specific parameters -- (NSRect)dragRectForTabCell:(PSMTabBarCell *)cell orientation:(PSMTabBarOrientation)orientation; -- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame; -- (NSRect)iconRectForTabCell:(PSMTabBarCell *)cell; -- (NSRect)indicatorRectForTabCell:(PSMTabBarCell *)cell; -- (NSRect)objectCounterRectForTabCell:(PSMTabBarCell *)cell; -- (CGFloat)minimumWidthOfTabCell:(PSMTabBarCell *)cell; -- (CGFloat)desiredWidthOfTabCell:(PSMTabBarCell *)cell; -- (CGFloat)tabCellHeight; - -// cell values -- (NSAttributedString *)attributedObjectCountValueForTabCell:(PSMTabBarCell *)cell; -- (NSAttributedString *)attributedStringValueForTabCell:(PSMTabBarCell *)cell; - -// drawing -- (void)drawTabCell:(PSMTabBarCell *)cell; -- (void)drawTabCellForDragImage:(PSMTabBarCell *)cell; -- (void)drawBackgroundInRect:(NSRect)rect; -- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect; - -@end - -@interface PSMTabBarControl (StyleAccessors) - -- (NSMutableArray *)cells; - -@end diff --git a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h deleted file mode 100644 index 502b3139e..000000000 --- a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// $Id: PSMSequelProTabStyle.h 2317 2010-06-15 10:19:41Z avenjamin $ -// -// PSMSequelProTabStyle.h -// sequel-pro -// -// Created by Ben Perry on June 15, 2010 -// -// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// More info at - -#import -#import "PSMTabStyle.h" - -@interface PSMSequelProTabStyle : NSObject -{ - NSImage *sequelProCloseButton; - NSImage *sequelProCloseDirtyButton; - NSImage *sequelProCloseDirtyButtonDown; - NSImage *sequelProCloseDirtyButtonOver; - NSImage *_addTabButtonImage; - - NSDictionary *_objectCountStringAttributes; - - PSMTabBarOrientation orientation; - PSMTabBarControl *tabBar; -} - -- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView *)controlView; - -- (void)encodeWithCoder:(NSCoder *)aCoder; -- (instancetype)initWithCoder:(NSCoder *)aDecoder; -@end diff --git a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m deleted file mode 100644 index 00b8f5198..000000000 --- a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m +++ /dev/null @@ -1,695 +0,0 @@ -// -// PSMSequelProTabStyle.m -// sequel-pro -// -// Created by Ben Perry on June 15, 2010 -// -// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// More info at - -#import "PSMSequelProTabStyle.h" -#import "PSMTabBarCell.h" -#import "PSMTabBarControl.h" -#import "NSBezierPath_AMShading.h" -#import "PSMTabDragAssistant.h" - -#import "sequel-ace-Swift.h" - -#define kPSMSequelProObjectCounterRadius 7.0f -#define kPSMSequelProCounterMinWidth 20 -#define kPSMSequelProTabCornerRadius 0 - -@interface PSMSequelProTabStyle () - -- (NSColor *)_lineColorForTabCellDrawing; -- (void)_drawTabCell:(PSMTabBarCell *)cell withBackgroundColor:(NSColor *)backgroundColor lineColor:(NSColor *)lineColor; -- (BOOL)isInDarkMode; - -@end - -@implementation PSMSequelProTabStyle - -- (NSString *)name -{ - return @"SequelPro"; -} - -#pragma mark - -#pragma mark Creation/Destruction - -- (id) init -{ - if ( (self = [super init]) ) { - NSBundle *bundle = [PSMTabBarControl bundle]; - - if (@available(macOS 11.0, *)) { - sequelProCloseButton = [NSImage imageWithSystemSymbolName:@"xmark.circle" accessibilityDescription:nil]; - } else { - sequelProCloseButton = [NSImage imageNamed:NSImageNameStopProgressTemplate]; - } - - sequelProCloseDirtyButton = [[NSImage alloc] initByReferencingFile:[bundle pathForImageResource:@"SequelProTabDirty"]]; - sequelProCloseDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[bundle pathForImageResource:@"SequelProTabDirty_Pressed"]]; - sequelProCloseDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[bundle pathForImageResource:@"SequelProTabDirty_Rollover"]]; - - if (@available(macOS 11.0, *)) { - _addTabButtonImage = [NSImage imageWithSystemSymbolName:@"plus" accessibilityDescription:nil]; - } else { - _addTabButtonImage = [NSImage imageNamed:NSImageNameAddTemplate]; - } - - _objectCountStringAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: - [[NSFontManager sharedFontManager] convertFont:[NSFont fontWithName:@"Helvetica" size:11.0f] toHaveTrait:NSBoldFontMask], NSFontAttributeName, - [[NSColor whiteColor] colorWithAlphaComponent:0.85f], NSForegroundColorAttributeName, nil, nil]; - } - return self; -} - -#pragma mark - -#pragma mark Detect Dark Aqua Mode - -- (BOOL)isInDarkMode -{ - if (@available(macOS 10.14, *)) { - NSAppearance *appearance = [NSAppearance currentAppearance] ?: [NSApp effectiveAppearance]; - NSAppearanceName match = [appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]]; - - if ([NSAppearanceNameDarkAqua isEqualToString:match]) { - return YES; - } - } - return NO; -} - -#pragma mark - -#pragma mark Control Specific - -- (CGFloat)leftMarginForTabBarControl -{ - return 0.0f; -} - -- (CGFloat)rightMarginForTabBarControl -{ - return 10.0f; // enough to fit plus button -} - -- (CGFloat)topMarginForTabBarControl -{ - return 10.0f; -} - -- (void)setOrientation:(PSMTabBarOrientation)value -{ - // Hard code orientation to horizontal - orientation = PSMTabBarHorizontalOrientation; -} - -#pragma mark - -#pragma mark Add Tab Button - -- (NSImage *)addTabButtonImage { - return [_addTabButtonImage imageWithOverlayColor:[self isInDarkMode] ? [NSColor whiteColor] : [NSColor blackColor]]; -} - -#pragma mark - -#pragma mark Cell Specific - -- (NSRect)dragRectForTabCell:(PSMTabBarCell *)cell orientation:(PSMTabBarOrientation)tabOrientation -{ - NSRect dragRect = [cell frame]; - dragRect.size.width++; - - if ([cell tabState] & PSMTab_SelectedMask) { - if (tabOrientation == PSMTabBarHorizontalOrientation) { - dragRect.origin.x -= 5.0f; - dragRect.size.width += 10.0f; - } else { - dragRect.size.height += 1.0f; - dragRect.origin.y -= 1.0f; - dragRect.origin.x += 2.0f; - dragRect.size.width -= 3.0f; - } - } else if (tabOrientation == PSMTabBarVerticalOrientation) { - dragRect.origin.x--; - } - - return dragRect; -} - -- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame -{ - if ([cell hasCloseButton] == NO) { - return NSZeroRect; - } - - NSRect result; - result.size = [sequelProCloseButton size]; - result.origin.x = cellFrame.origin.x + MARGIN_X; - result.origin.y = cellFrame.origin.y + MARGIN_Y; - - return result; -} - -- (NSRect)iconRectForTabCell:(PSMTabBarCell *)cell -{ - NSRect cellFrame = [cell frame]; - - if ([cell hasIcon] == NO) { - return NSZeroRect; - } - - NSRect result; - result.size = NSMakeSize(kPSMTabBarIconWidth, kPSMTabBarIconWidth); - result.origin.x = cellFrame.origin.x + MARGIN_X; - result.origin.y = cellFrame.origin.y + MARGIN_Y; - - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { - result.origin.x += [sequelProCloseButton size].width + kPSMTabBarCellPadding; - } - - return result; -} - -- (NSRect)indicatorRectForTabCell:(PSMTabBarCell *)cell -{ - NSRect cellFrame = [cell frame]; - - if ([[cell indicator] isHidden]) { - return NSZeroRect; - } - - NSRect result; - result.size = NSMakeSize(kPSMTabBarIndicatorWidth, kPSMTabBarIndicatorWidth); - result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - kPSMTabBarIndicatorWidth; - result.origin.y = cellFrame.origin.y + MARGIN_Y; - - return result; -} - -- (NSRect)objectCounterRectForTabCell:(PSMTabBarCell *)cell -{ - NSRect cellFrame = [cell frame]; - - if ([cell count] == 0) { - return NSZeroRect; - } - - CGFloat countWidth = [[self attributedObjectCountValueForTabCell:cell] size].width; - countWidth += (2 * kPSMSequelProObjectCounterRadius - 6.0f); - if (countWidth < kPSMSequelProCounterMinWidth) { - countWidth = kPSMSequelProCounterMinWidth; - } - - NSRect result; - result.size = NSMakeSize(countWidth, 2 * kPSMSequelProObjectCounterRadius); // temp - result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - result.size.width; - result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0f; - - if (![[cell indicator] isHidden]) { - result.origin.x -= kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding; - } - - return result; -} - -- (CGFloat)minimumWidthOfTabCell:(PSMTabBarCell *)cell -{ - CGFloat resultWidth = 0.0f; - - // left margin - resultWidth = MARGIN_X; - - // close button? - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { - resultWidth += [sequelProCloseButton size].width + kPSMTabBarCellPadding; - } - - // icon? - if ([cell hasIcon]) { - resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding; - } - - // the label - resultWidth += kPSMMinimumTitleWidth; - - // object counter? - if ([cell count] > 0) { - resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding; - } - - // indicator? - if ([[cell indicator] isHidden] == NO) - resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth; - - // right margin - resultWidth += MARGIN_X; - - return ceilf(resultWidth); -} - -- (CGFloat)desiredWidthOfTabCell:(PSMTabBarCell *)cell -{ - CGFloat resultWidth = 0.0f; - - // left margin - resultWidth = MARGIN_X; - - // close button? - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) - resultWidth += [sequelProCloseButton size].width + kPSMTabBarCellPadding; - - // icon? - if ([cell hasIcon]) { - resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding; - } - - // the label - resultWidth += [[cell attributedStringValue] size].width; - - // object counter? - if ([cell count] > 0) { - resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding; - } - - // indicator? - if ([[cell indicator] isHidden] == NO) - resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth; - - // right margin - resultWidth += MARGIN_X; - - return ceilf(resultWidth); -} - -- (CGFloat)tabCellHeight -{ - return kPSMTabBarControlHeight; -} - -#pragma mark - -#pragma mark Cell Values - -- (NSAttributedString *)attributedObjectCountValueForTabCell:(PSMTabBarCell *)cell -{ - NSString *contents = [NSString stringWithFormat:@"%lu", (unsigned long)[cell count]]; - - return [[NSMutableAttributedString alloc] initWithString:contents attributes:_objectCountStringAttributes]; -} - -- (NSAttributedString *)attributedStringValueForTabCell:(PSMTabBarCell *)cell -{ - NSMutableAttributedString *attrStr; - NSString *contents = [cell stringValue]; - attrStr = [[NSMutableAttributedString alloc] initWithString:contents]; - NSRange range = NSMakeRange(0, [contents length]); - - // Add font attribute - [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0f] range:range]; - [attrStr addAttribute:NSForegroundColorAttributeName value:[NSColor textColor] range:range]; - - // Add shadow attribute - NSShadow* textShadow; - textShadow = [[NSShadow alloc] init]; - CGFloat shadowAlpha; - if (([cell state] == NSOnState) || [cell isHighlighted]) { - shadowAlpha = 0.8f; - } else { - shadowAlpha = 0.5f; - } - [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0f alpha:shadowAlpha]]; - [textShadow setShadowOffset:NSMakeSize(0, -1)]; - [textShadow setShadowBlurRadius:1.0f]; - - // Paragraph Style for Truncating Long Text - static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil; - if (!TruncatingTailParagraphStyle) { - TruncatingTailParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - [TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; - [TruncatingTailParagraphStyle setAlignment:NSTextAlignmentCenter]; - } - [attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range]; - - return attrStr; -} - -#pragma mark - -#pragma mark Drawing - -// Step 1 -- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect -{ - if (orientation != [bar orientation]) { - orientation = [bar orientation]; - } - - if (tabBar != bar) { - tabBar = bar; - } - - [self drawBackgroundInRect:rect]; - - // no tab view == not connected - if (![bar tabView]) { - NSRect labelRect = rect; - labelRect.size.height -= 4.0f; - labelRect.origin.y += 4.0f; - NSMutableAttributedString *attrStr; - NSString *contents = @"PSMTabBarControl"; - attrStr = [[NSMutableAttributedString alloc] initWithString:contents]; - NSRange range = NSMakeRange(0, [contents length]); - [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0f] range:range]; - NSMutableParagraphStyle *centeredParagraphStyle = nil; - - if (!centeredParagraphStyle) { - centeredParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - [centeredParagraphStyle setAlignment:NSTextAlignmentCenter]; - } - [attrStr addAttribute:NSParagraphStyleAttributeName value:centeredParagraphStyle range:range]; - [attrStr drawInRect:labelRect]; - return; - } - - // draw cells - NSEnumerator *e = [[bar cells] objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - if ((![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) { - [cell drawWithFrame:[cell frame] inView:bar]; - } - } -} - -// Step 2 -- (void)drawBackgroundInRect:(NSRect)rect -{ - // Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area - rect = [tabBar bounds]; - - // Find active cell - PSMTabBarCell *selectedCell = nil; - - for (PSMTabBarCell *aCell in [tabBar cells]) { - if (aCell.tabState & PSMTab_SelectedMask) { - selectedCell = aCell; - break; - } - } - - [NSGraphicsContext saveGraphicsState]; - [[NSGraphicsContext currentContext] setShouldAntialias:NO]; - - float backgroundCalibratedWhite = 0.73f; - - float lineCalibratedWhite = [[NSColor grayColor] whiteComponent]; - float shadowAlpha = 0.4f; - - // When the window is in the background, tone down the colours - if ((![[tabBar window] isMainWindow] && ![[[tabBar window] attachedSheet] isMainWindow]) || ![NSApp isActive]) { - backgroundCalibratedWhite = 0.86f; - lineCalibratedWhite = 0.49f; - shadowAlpha = 0.3f; - } - - if ([self isInDarkMode]) { - backgroundCalibratedWhite -= 0.55f; - lineCalibratedWhite -= 0.39f; - shadowAlpha -= 0.1f; - } - - // Fill in background of tab bar - if (tabBar.cells.count != 1) { // multiple tabs - fill with background color - [[NSColor colorWithCalibratedWhite:backgroundCalibratedWhite alpha:1.0f] set]; - } else { // When there's only one tab, the tabs are probably hidden, so use the selected cell's highlight colour as our background colour - [[self fillColorForCell:selectedCell] set]; - } - NSRectFill(NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); - - // Draw horizontal line across the top edge - [[NSColor colorWithCalibratedWhite:lineCalibratedWhite alpha:1.0f] set]; - [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + 0.5f) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + 0.5f)]; - - // Draw horizontal line across the bottom edge - [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height - 0.5f) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - 0.5f)]; - - [NSGraphicsContext restoreGraphicsState]; -} - -// Step 3 -- (void)drawTabCell:(PSMTabBarCell *)cell { - NSColor *lineColor = [self _lineColorForTabCellDrawing]; - NSColor *fillColor = [self fillColorForCell:cell]; - - [self _drawTabCell:cell withBackgroundColor:fillColor lineColor:lineColor]; - - [self drawInteriorWithTabCell:cell inView:[cell customControlView]]; -} - -/** - * Same as above, but doesn't draw the left hand (right had of the actual tab) border for the tab drag image. - */ -- (void)drawTabCellForDragImage:(PSMTabBarCell *)cell -{ - NSColor *fillColor = [self fillColorForCell:cell]; - - [self _drawTabCell:cell withBackgroundColor:fillColor lineColor:nil]; - - [self drawInteriorWithTabCell:cell inView:[cell customControlView]]; -} - -// Step 4 -- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView -{ - NSRect cellFrame = [cell frame]; - CGFloat insetLabelWidth = 0; - - // close button - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed] && [cell isHighlighted]) { - - NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame]; - NSImage *closeButton = nil; - - closeButton = [cell isEdited] ? sequelProCloseDirtyButton : sequelProCloseButton; - closeButton = [closeButton imageWithOverlayColor:[self isInDarkMode] ? [NSColor whiteColor] : [NSColor blackColor]]; - - // Slightly darken background tabs on mouse over - if ([cell state] == NSOffState) { - NSColor *lineColor = [self _lineColorForTabCellDrawing]; - NSColor *fillColor = [[self fillColorForCell:cell] shadowWithLevel:0.03f]; - - [self _drawTabCell:cell withBackgroundColor:fillColor lineColor:lineColor]; - } - - [closeButton drawInRect:closeButtonRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0f respectFlipped:YES hints:nil]; - } - - // icon - if ([cell hasIcon]) { - NSRect iconRect = [self iconRectForTabCell:cell]; - NSImage *icon = [[[cell representedObject] identifier] icon]; - - // center in available space (in case icon image is smaller than kPSMTabBarIconWidth) - if ([icon size].width < kPSMTabBarIconWidth) { - iconRect.origin.x += (kPSMTabBarIconWidth - [icon size].width)/2.0f; - } - if ([icon size].height < kPSMTabBarIconWidth) { - iconRect.origin.y -= (kPSMTabBarIconWidth - [icon size].height)/2.0f; - } - - [icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0f respectFlipped:YES hints:nil]; - - // scoot label over - insetLabelWidth += iconRect.size.width + kPSMTabBarCellPadding; - } - else { - insetLabelWidth += [sequelProCloseButton size].width + kPSMTabBarCellPadding; - } - - // label rect - NSRect labelRect; - labelRect.origin.x = cellFrame.origin.x + MARGIN_X + insetLabelWidth; - labelRect.size.width = cellFrame.size.width - (labelRect.origin.x - cellFrame.origin.x) - insetLabelWidth - MARGIN_X; - labelRect.size.height = cellFrame.size.height; - labelRect.origin.y = cellFrame.origin.y + MARGIN_Y; - - // object counter - if ([cell count] > 0) { - [[cell countColor] ?: [NSColor colorWithCalibratedWhite:0.3f alpha:0.6f] set]; - NSBezierPath *path = [NSBezierPath bezierPath]; - NSRect myRect = [self objectCounterRectForTabCell:cell]; - [path moveToPoint:NSMakePoint(myRect.origin.x + kPSMSequelProObjectCounterRadius, myRect.origin.y)]; - [path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMSequelProObjectCounterRadius, myRect.origin.y)]; - [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMSequelProObjectCounterRadius, myRect.origin.y + kPSMSequelProObjectCounterRadius) radius:kPSMSequelProObjectCounterRadius startAngle:270.0f endAngle:90.0f]; - [path lineToPoint:NSMakePoint(myRect.origin.x + kPSMSequelProObjectCounterRadius, myRect.origin.y + myRect.size.height)]; - [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMSequelProObjectCounterRadius, myRect.origin.y + kPSMSequelProObjectCounterRadius) radius:kPSMSequelProObjectCounterRadius startAngle:90.0f endAngle:270.0f]; - [path fill]; - - // draw attributed string centered in area - NSRect counterStringRect; - NSAttributedString *counterString = [self attributedObjectCountValueForTabCell:cell]; - counterStringRect.size = [counterString size]; - counterStringRect.origin.x = myRect.origin.x + ((myRect.size.width - counterStringRect.size.width) / 2.0f) + 0.25f; - counterStringRect.origin.y = myRect.origin.y + ((myRect.size.height - counterStringRect.size.height) / 2.0f) + 0.5f; - [counterString drawInRect:counterStringRect]; - - // shrink label width to make room for object counter - labelRect.size.width -= myRect.size.width + kPSMTabBarCellPadding; - } - - // determine text colour - NSAttributedString *labelString = cell.attributedStringValue; - if (cell.state != NSOnState) { - NSMutableAttributedString *newLabelString = labelString.mutableCopy; - NSColor *textColor = [NSColor darkGrayColor]; - if ([self isInDarkMode]) { - textColor = [cell backgroundColor] ? [NSColor blackColor] : [NSColor lightGrayColor]; - } - - [newLabelString addAttribute:NSForegroundColorAttributeName value:textColor range:NSMakeRange(0, newLabelString.length)]; - labelString = newLabelString.copy; - } - - // draw label - [labelString drawInRect:labelRect]; -} - -- (NSColor *)fillColorForCell:(PSMTabBarCell *)cell -{ - NSColor *fillColor = nil; - NSColor *cellBackgroundColor = [[cell backgroundColor] copy]; // seems to be almost always nil, but take a copy as we've seen memory issues - - // Set up colours - if (([[tabBar window] isMainWindow] || [[[tabBar window] attachedSheet] isMainWindow]) && [NSApp isActive]) { - if ([cell state] == NSOnState) { //active window, active cell - float tabWhiteComponent = 0.795f; - if (!tabBar.window.toolbar.isVisible) tabWhiteComponent += 0.02f; - if ([self isInDarkMode]) tabWhiteComponent -= 0.55f; - - fillColor = [NSColor colorWithCalibratedWhite:tabWhiteComponent alpha:1.0f]; - - if(cellBackgroundColor) { - fillColor = [self isInDarkMode] ? [cellBackgroundColor shadowWithLevel:0.25] : cellBackgroundColor; - } - } else { //active window, background cell - float tabWhiteComponent = 0.68f; - if ([self isInDarkMode]) tabWhiteComponent -= 0.51f; - - fillColor = [NSColor colorWithCalibratedWhite:tabWhiteComponent alpha:1.0f]; - - if(cellBackgroundColor) { - //should be a slightly darker variant of the color - fillColor = [self isInDarkMode] ? [cellBackgroundColor shadowWithLevel:0.40] : [cellBackgroundColor shadowWithLevel:0.15]; - - // also desaturate the color - fillColor = [NSColor colorWithCalibratedHue:fillColor.hueComponent saturation:fillColor.saturationComponent * 0.4 brightness:fillColor.brightnessComponent alpha:1.0f]; - } - } - } else { - if ([cell state] == NSOnState) { //background window, active cell - float tabWhiteComponent = 0.957f; - if (!tabBar.window.toolbar.isVisible) tabWhiteComponent += 0.01f; - if ([self isInDarkMode]) tabWhiteComponent -= 0.75f; - - //create a slightly desaturated variant (gray can't be desaturated so we instead make it brighter) - if (cell.backgroundColor) { - NSColor *backgroundRgb = [cellBackgroundColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - fillColor = [NSColor colorWithCalibratedHue:backgroundRgb.hueComponent saturation:backgroundRgb.saturationComponent brightness:(backgroundRgb.brightnessComponent * 1.28f) alpha:1.0f]; - } else { - fillColor = [NSColor colorWithCalibratedWhite:tabWhiteComponent alpha:1.0f]; - } - - } else { //background window, background cell - float tabWhiteComponent = 0.86f; - if ([self isInDarkMode]) tabWhiteComponent -= 0.7f; - - fillColor = [NSColor colorWithCalibratedWhite:tabWhiteComponent alpha:1.0f]; - - //make it dark first, then desaturate - if (cellBackgroundColor) { - NSColor *dark = [[cellBackgroundColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace] shadowWithLevel:0.15]; - fillColor = [NSColor colorWithCalibratedHue:dark.hueComponent saturation:dark.saturationComponent * 0.15 brightness:(dark.brightnessComponent * 1.28) alpha:1.0f]; - } - } - } - - return fillColor; -} - -#pragma mark - -#pragma mark Archiving - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - return [self init]; -} - -#pragma mark - -#pragma mark Private API - -- (void)_drawTabCell:(PSMTabBarCell *)cell withBackgroundColor:(NSColor *)backgroundColor lineColor:(NSColor *)lineColor -{ - NSRect cellFrame = [cell frame]; - - // Setup fill rect - NSRect fillRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y + 1, cellFrame.size.width, cellFrame.size.height - 1.5); - - // Draw - [NSGraphicsContext saveGraphicsState]; - - [backgroundColor set]; - NSRectFill(fillRect); - - if (lineColor) { - - // Stroke left edge - [lineColor setStroke]; - - NSPoint point1 = NSMakePoint(fillRect.origin.x + fillRect.size.width - 0.5, fillRect.origin.y); - NSPoint point2 = NSMakePoint(fillRect.origin.x + fillRect.size.width - 0.5, fillRect.origin.y + fillRect.size.height); - - [NSBezierPath strokeLineFromPoint:point1 toPoint:point2]; - } - - [NSGraphicsContext restoreGraphicsState]; -} - -- (NSColor *)_lineColorForTabCellDrawing -{ - NSColor *lineColor = nil; - - if (([[tabBar window] isMainWindow] || [[[tabBar window] attachedSheet] isMainWindow]) && [NSApp isActive]) { - if ([self isInDarkMode]) { - lineColor = [NSColor colorWithCalibratedWhite:0.29f alpha:.42f]; - } else { - lineColor = [NSColor grayColor]; - } - } - else { - if ([self isInDarkMode]) { - lineColor = [NSColor colorWithCalibratedWhite:0.19f alpha:.42f]; - } else { - lineColor = [NSColor colorWithCalibratedWhite:0.49f alpha:1.0f]; - } - } - - return lineColor; -} - -@end diff --git a/Interfaces/DBView.xib b/Interfaces/DBView.xib index f964b392e..4c9accae6 100644 --- a/Interfaces/DBView.xib +++ b/Interfaces/DBView.xib @@ -2512,7 +2512,7 @@ Gw - + @@ -2621,7 +2621,7 @@ Gw - + @@ -2708,7 +2708,7 @@ Gw - + @@ -2813,7 +2813,7 @@ Gw - + @@ -2880,7 +2880,7 @@ Gw - + @@ -2998,7 +2998,7 @@ Gw - + @@ -3109,7 +3109,7 @@ Gw - + @@ -3177,7 +3177,7 @@ Gw - + @@ -3253,7 +3253,7 @@ Gw - + @@ -3509,7 +3509,7 @@ Gw - + @@ -3662,7 +3662,7 @@ DQ - + @@ -3717,7 +3717,7 @@ Gw - + @@ -3775,7 +3775,7 @@ DQ - + @@ -3885,7 +3885,7 @@ Gw - + @@ -3966,7 +3966,7 @@ Gw - + @@ -4038,7 +4038,7 @@ Gw - + @@ -4886,7 +4886,7 @@ Gw - + diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 85a5e95ff..464f1282f 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -1742,7 +1742,6 @@ - (void)_restoreConnectionInterface // Reset the window title [dbDocument updateWindowTitle:self]; - [[dbDocument parentTabViewItem] setLabel:[dbDocument displayName]]; // Stop the current tab's progress indicator [dbDocument setIsProcessing:NO]; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index ec9c57051..1d92209e4 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -241,7 +241,6 @@ NSInteger confirmCopyDatabaseReturnCode; // Properties - NSTabViewItem *parentTabViewItem; BOOL isProcessing; NSString *processID; BOOL windowTitleStatusViewIsVisible; @@ -254,7 +253,6 @@ @property (nonatomic, strong) NSTableView *dbTablesTableView; @property (readwrite, strong) NSURL *sqlFileURL; @property (readwrite) NSStringEncoding sqlFileEncoding; -@property (readwrite, strong) NSTabViewItem *parentTabViewItem; @property (readwrite) BOOL isProcessing; @property (readwrite, copy) NSString *processID; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index e42086524..1121580b9 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -82,8 +82,6 @@ #import "SPSSHTunnel.h" #import "SPHelpViewerClient.h" #import "SPHelpViewerController.h" -#import "PSMTabBarController.h" -#import "PSMTabBarControl.h" #import "SPPrintUtility.h" #import "SPBundleManager.h" @@ -140,7 +138,6 @@ @implementation SPDatabaseDocument @synthesize sqlFileURL; @synthesize sqlFileEncoding; -@synthesize parentTabViewItem; @synthesize isProcessing; @synthesize serverSupport; @synthesize databaseStructureRetrieval; @@ -458,13 +455,7 @@ - (void)setConnection:(SPMySQLConnection *)theConnection [self updateWindowTitle:self]; - NSString *serverDisplayName = nil; - if ([self.parentWindowController selectedTableDocument] == self) { - serverDisplayName = [[self.parentWindowController window] title]; - } else { - serverDisplayName = [parentTabViewItem label]; - } - + NSString *serverDisplayName = [[self.parentWindowController window] title]; NSUserNotification *notification = [[NSUserNotification alloc] init]; notification.title = @"Connected"; notification.informativeText=[NSString stringWithFormat:NSLocalizedString(@"Connected to %@", @"description for connected notification"), serverDisplayName]; @@ -2338,7 +2329,6 @@ - (void)closeConnection // Disconnected notification NSUserNotification *notification = [[NSUserNotification alloc] init]; notification.title = @"Disconnected"; - notification.informativeText=[NSString stringWithFormat:NSLocalizedString(@"Disconnected from %@", @"description for disconnected notification"), [parentTabViewItem label]]; notification.soundName = NSUserNotificationDefaultSoundName; [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; @@ -3301,8 +3291,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem if (!_isConnected || _isWorkingLevel) { return ( action == @selector(newWindow:) || - action == @selector(terminate:) || - action == @selector(closeTab:) + action == @selector(terminate:) ); } @@ -3536,11 +3525,7 @@ - (void) updateWindowTitle:(id)sender // Ensure a call on the main thread if (![NSThread isMainThread]) return [[self onMainThread] updateWindowTitle:sender]; - NSMutableString *tabTitle; NSMutableString *windowTitle; - SPDatabaseDocument *frontTableDocument = [self.parentWindowController selectedTableDocument]; - - NSColor *tabColor = nil; // Determine name details NSString *pathName = @""; @@ -3550,17 +3535,12 @@ - (void) updateWindowTitle:(id)sender if ([connectionController isConnecting]) { windowTitle = [NSMutableString stringWithString:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; - tabTitle = windowTitle; } else if (!_isConnected) { windowTitle = [NSMutableString stringWithFormat:@"%@%@", pathName, [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]]; - tabTitle = windowTitle; } else { - tabColor = [[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]; - windowTitle = [NSMutableString string]; - tabTitle = [NSMutableString string]; // Add the path to the window title [windowTitle appendString:pathName]; @@ -3571,37 +3551,17 @@ - (void) updateWindowTitle:(id)sender // Add the name to the window [windowTitle appendString:[self name]]; - // Also add to the non-front tabs if the host is different, not connected, or no db is selected - if ([[frontTableDocument name] isNotEqualTo:[self name]] || ![frontTableDocument getConnection] || ![self database]) { - [tabTitle appendString:[self name]]; - } - // If a database is selected, add to the window - and other tabs if host is the same but db different or table is not set if ([self database]) { [windowTitle appendFormat:@"/%@", [self database]]; - if (frontTableDocument == self - || ![frontTableDocument getConnection] - || [[frontTableDocument name] isNotEqualTo:[self name]] - || [[frontTableDocument database] isNotEqualTo:[self database]] - || ![[self table] length]) - { - if ([tabTitle length]) [tabTitle appendString:@"/"]; - [tabTitle appendString:[self database]]; - } } // Add the table name if one is selected if ([[self table] length]) { [windowTitle appendFormat:@"/%@", [self table]]; - if ([tabTitle length]) [tabTitle appendString:@"/"]; - [tabTitle appendString:[self table]]; } } - // Set the titles - [parentTabViewItem setLabel:tabTitle]; - [parentTabViewItem setColor:tabColor]; - if ([self.parentWindowController selectedTableDocument] == self) { [[self.parentWindowController window] setTitle:windowTitle]; } @@ -3955,7 +3915,6 @@ - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem - (void)makeKeyDocument { [[[self.parentWindowController window] onMainThread] makeKeyAndOrderFront:self]; - [[[[self parentTabViewItem] onMainThread] tabView] selectTabViewItemWithIdentifier:self]; } /** @@ -4721,12 +4680,7 @@ - (void)restoreSession */ - (void)connectionControllerInitiatingConnection:(SPConnectionController *)controller { - // Update the window title to indicate that we are trying to establish a connection - [parentTabViewItem setLabel:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; - - if ([self.parentWindowController selectedTableDocument] == self) { - [[self.parentWindowController window] setTitle:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; - } + [[self.parentWindowController window] setTitle:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; } /** @@ -6575,18 +6529,9 @@ - (void)closeAndDisconnect _isConnected = NO; - if ([[[self parentTabViewItem] tabView] numberOfTabViewItems] == 1) { - [theParentWindow orderOut:self]; - [theParentWindow setAlphaValue:0.0f]; - [theParentWindow performSelector:@selector(close) withObject:nil afterDelay:1.0]; - } - else { - NSTabViewItem *parentTabViewItemTmp = [self parentTabViewItem]; - if([parentTabViewItemTmp.tabView.tabViewItems containsObject:parentTabViewItemTmp]){ - [[parentTabViewItemTmp tabView] performSelector:@selector(removeTabViewItem:) withObject:parentTabViewItemTmp afterDelay:0.5]; - } - [theParentWindow performSelector:@selector(makeKeyAndOrderFront:) withObject:nil afterDelay:0.6]; - } + [theParentWindow orderOut:self]; + [theParentWindow setAlphaValue:0.0f]; + [theParentWindow performSelector:@selector(close) withObject:nil afterDelay:1.0]; [self parentTabDidClose]; } diff --git a/Source/Controllers/SPAppController.h b/Source/Controllers/SPAppController.h index 723cf1d43..c626ce3fb 100755 --- a/Source/Controllers/SPAppController.h +++ b/Source/Controllers/SPAppController.h @@ -115,6 +115,4 @@ - (IBAction)newTab:(id)sender; - (IBAction)duplicateTab:(id)sender; -- (void)tabDragStarted:(id)sender; - @end diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 9064e8e02..029624592 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -49,7 +49,6 @@ #import "SPCopyTable.h" #import "SPSyntaxParser.h" #import "SPTextView.h" -#import "PSMTabBarControl.h" #import "SPFunctions.h" #import "SPBundleManager.h" #import "MGTemplateEngine.h" @@ -195,9 +194,6 @@ - (void)awakeFromNib // Register SPAppController for AppleScript events [[NSScriptExecutionContext sharedScriptExecutionContext] setTopLevelObject:self]; - - // Register for drag start notifications - used to bring all windows to front - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tabDragStarted:) name:PSMTabDragDidBeginNotification object:nil]; } /** @@ -651,6 +647,7 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { for (NSDictionary *window in [[[spfs objectForKey:@"windows"] reverseObjectEnumerator] allObjects]) { // Create a new window controller, and set up a new connection view within it. SPWindowController *newWindowController = [[SPWindowController alloc] init]; + [newWindowController showWindow:self]; [self.windowControllers addObject:newWindowController]; NSWindow *newWindow = [newWindowController window]; @@ -1534,13 +1531,14 @@ - (SPWindowController *)newWindowController { // Create a new window controller, and set up a new connection view within it. SPWindowController *newWindowController = [[SPWindowController alloc] init]; +// [newWindowController showWindow:self]; newWindowController.delegate = self; NSWindow *newWindow = [newWindowController window]; // 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; +// 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 @@ -1548,14 +1546,14 @@ - (SPWindowController *)newWindowController { BOOL usedAutosave = [newWindow setFrameAutosaveName:@"DBView"]; if (!usedAutosave) { - [newWindow setFrameUsingName:@"DBView"]; +// [newWindow setFrameUsingName:@"DBView"]; } // Add the connection view [newWindowController addNewConnection]; // Cascade according to the statically stored cascade location. - cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; +// cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; // Set the window controller as the window's delegate [newWindow setDelegate:newWindowController]; @@ -1654,14 +1652,6 @@ - (IBAction)duplicateTab:(id)sender [newConnection setState:frontState]; } -/** - * When tab drags start, bring all the windows in front of other applications. - */ -- (void)tabDragStarted:(id)sender -{ - [NSApp arrangeInFront:self]; -} - #pragma mark - NSWindowDelegate - (void)windowWillClose:(NSNotification *)notification diff --git a/Source/Controllers/Window/SPWindowController.m b/Source/Controllers/Window/SPWindowController.m index 1e83ed84d..67ee26ea5 100644 --- a/Source/Controllers/Window/SPWindowController.m +++ b/Source/Controllers/Window/SPWindowController.m @@ -31,14 +31,10 @@ #import "SPWindowController.h" #import "SPDatabaseDocument.h" #import "SPAppController.h" -#import "PSMTabDragAssistant.h" #import "SPConnectionController.h" #import "SPFavoritesOutlineView.h" #import "SPWindow.h" -#import "PSMTabBarControl.h" -#import "PSMTabStyle.h" - #import "sequel-ace-Swift.h" @interface SPWindowController () @@ -57,39 +53,43 @@ @implementation SPWindowController - (instancetype)init { SPWindow *newWindow = [[SPWindow alloc] init]; - if (self = [self initWithWindow:newWindow]) { + [newWindow setContentMinSize:NSMakeSize(800, 400)]; + [newWindow setMinSize:NSMakeSize(800, 400)]; + if (self = [super initWithWindow:newWindow]) { - } - return self; -} - -- (void)windowDidLoad { - [super windowDidLoad]; + [self setupAppearance]; + [self setupConstraints]; - [self setupAppearance]; - [self setupConstraints]; + [self _switchOutSelectedTableDocument:nil]; - [self _switchOutSelectedTableDocument:nil]; + [newWindow setCollectionBehavior:[newWindow collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; - NSWindow *window = [self window]; + // Disable automatic cascading - this occurs before the size is set, so let the app + // controller apply cascading after frame autosaving. + [self setShouldCascadeWindows:NO]; - [window setCollectionBehavior:[window collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; + // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. + NSMenu *mainMenu = [NSApp mainMenu]; + _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; + _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; - // Disable automatic cascading - this occurs before the size is set, so let the app - // controller apply cascading after frame autosaving. - [self setShouldCascadeWindows:NO]; + // Because we are a document-based app we automatically adopt window restoration on 10.7+. + // However that causes a race condition with our own window setup code. + // Remove this when we actually support restoration. + if ([newWindow respondsToSelector:@selector(setRestorable:)]) { + [newWindow setRestorable:NO]; + } + newWindow.autorecalculatesKeyViewLoop = NO; + } + return self; +} - // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. - NSMenu *mainMenu = [NSApp mainMenu]; - _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; - _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; +- (void)awakeFromNib { + [super awakeFromNib]; +} - // Because we are a document-based app we automatically adopt window restoration on 10.7+. - // However that causes a race condition with our own window setup code. - // Remove this when we actually support restoration. - if ([window respondsToSelector:@selector(setRestorable:)]) { - [window setRestorable:NO]; - } +- (void)windowDidLoad { + [super windowDidLoad]; } #pragma mark - @@ -99,7 +99,9 @@ - (SPDatabaseDocument *)addNewConnection { // Create a new database connection view SPDatabaseDocument *databaseDocument = [[SPDatabaseDocument alloc] initWithWindowController:self]; - self.contentViewController = databaseDocument; + self.selectedTableDocument = databaseDocument; + self.window.contentView.autoresizesSubviews = YES; + [self.window.contentView addSubview:[databaseDocument databaseView]]; // Tell the new database connection view to set up the window and update titles [databaseDocument didBecomeActiveTabInWindow]; @@ -114,9 +116,9 @@ - (SPDatabaseDocument *)addNewConnection - (IBAction)closeTab:(id)sender { - //trying to close the window will itself call parentTabShouldClose for all tabs in windowShouldClose: - [[self window] performClose:self]; - [self.delegate windowControllerDidClose:self]; + //trying to close the window will itself call parentTabShouldClose for all tabs in windowShouldClose: + [[self window] performClose:self]; + [self.delegate windowControllerDidClose:self]; } /** diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index a4d414507..87be2bd21 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -16,16 +16,6 @@ extension SPWindowController { @objc func setupConstraints() { // Here we will set constraints in the future once we remove .xib, for now, commented out as it crashes -// tabBarControl.snp.makeConstraints { -// $0.top.equalToSuperview() -// $0.leading.trailing.equalToSuperview() -// $0.height.equalTo(25) -// } -// tabView.snp.makeConstraints { -// $0.top.equalTo(tabBarControl.snp.bottom) -// $0.leading.trailing.equalToSuperview() -// $0.bottom.equalToSuperview() -// } } } diff --git a/Source/Sequel-Ace-Bridging-Header.h b/Source/Sequel-Ace-Bridging-Header.h index 1414d159a..3ae9eb460 100644 --- a/Source/Sequel-Ace-Bridging-Header.h +++ b/Source/Sequel-Ace-Bridging-Header.h @@ -30,7 +30,6 @@ #import "SPAppController.h" #import "SPWindowController.h" #import "SPDatabaseDocument.h" -#import "PSMTabBarControl.h" #import "SPConstants.h" diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index af42157e0..ef8437b3b 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -40,12 +40,16 @@ @implementation SPWindow #pragma mark - -+ (void)initialize -{ - // Disable automatic window tabbing on 10.12+ - if ([NSWindow respondsToSelector:@selector(setAllowsAutomaticWindowTabbing:)]) { - [NSWindow setAllowsAutomaticWindowTabbing:NO]; - } +- (BOOL)isResizable { + return YES; +} + +- (BOOL)isMiniaturizable { + return YES; +} + +- (BOOL)isReleasedWhenClosed { + return YES; } #pragma mark - diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index a8058a509..2c4bf06e6 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -227,58 +227,7 @@ 50EA92681AB23EFC008D3C4F /* SPTableCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1141A388117BBFF200126A28 /* SPTableCopy.m */; }; 50EA926A1AB246B8008D3C4F /* SPDatabaseActionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EA92691AB246B8008D3C4F /* SPDatabaseActionTest.m */; }; 50F530521ABCF66B002F2C1A /* resetTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 50F530511ABCF66B002F2C1A /* resetTemplate.pdf */; }; - 511C466A25BC768E001AA1BD /* NSTabViewItemExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 511C466925BC768E001AA1BD /* NSTabViewItemExtension.swift */; }; 513515D2259354BB001E4533 /* NSImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513515D1259354BB001E4533 /* NSImageExtensions.swift */; }; - 513515E42593568B001E4533 /* PSMProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9071D11BD9B34000826E5 /* PSMProgressIndicator.m */; }; - 513515E52593568B001E4533 /* PSMTabDragAssistant.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072711BD9B34000826E5 /* PSMTabDragAssistant.m */; }; - 513515E62593568B001E4533 /* PSMOverflowPopUpButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9071B11BD9B34000826E5 /* PSMOverflowPopUpButton.m */; }; - 513515E72593568B001E4533 /* PSMTabBarControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072311BD9B34000826E5 /* PSMTabBarControl.m */; }; - 513515E82593568B001E4533 /* PSMTabBarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072111BD9B34000826E5 /* PSMTabBarCell.m */; }; - 513515E92593568B001E4533 /* PSMTabDragWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072B11BD9B34000826E5 /* PSMTabDragWindow.m */; }; - 513515EA2593568B001E4533 /* PSMTabDragWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072D11BD9B34000826E5 /* PSMTabDragWindowController.m */; }; - 513515EB2593568B001E4533 /* NSBezierPath_AMShading.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9071711BD9B34000826E5 /* NSBezierPath_AMShading.m */; }; - 513515EC2593568B001E4533 /* NSString_AITruncation.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9071911BD9B34000826E5 /* NSString_AITruncation.m */; }; - 513515ED2593568B001E4533 /* PSMTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072511BD9B34000826E5 /* PSMTabBarController.m */; }; - 513515EE2593568B001E4533 /* PSMTabDragView.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9072911BD9B34000826E5 /* PSMTabDragView.m */; }; - 513515EF2593568B001E4533 /* PSMRolloverButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9071F11BD9B34000826E5 /* PSMRolloverButton.m */; }; - 513515F425935691001E4533 /* PSMSequelProTabStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */; }; - 513515FD25935699001E4533 /* overflowImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070A11BD9B34000826E5 /* overflowImage.png */; }; - 513515FE25935699001E4533 /* SequelProTabDirty_Rollover@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 58C4BA1216781A93004068AB /* SequelProTabDirty_Rollover@2x.png */; }; - 513515FF25935699001E4533 /* AdiumGradient.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FA11BD9B34000826E5 /* AdiumGradient.png */; }; - 5135160025935699001E4533 /* TabNewMetal.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071311BD9B34000826E5 /* TabNewMetal.png */; }; - 5135160125935699001E4533 /* TabClose_Front_Rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071211BD9B34000826E5 /* TabClose_Front_Rollover.png */; }; - 5135160225935699001E4533 /* SequelProTabDirty_Pressed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 58C4BA1116781A93004068AB /* SequelProTabDirty_Pressed@2x.png */; }; - 5135160325935699001E4533 /* AquaTabClose_Front_Rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FD11BD9B34000826E5 /* AquaTabClose_Front_Rollover.png */; }; - 5135160425935699001E4533 /* TabNewMetalRollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071511BD9B34000826E5 /* TabNewMetalRollover.png */; }; - 5135160525935699001E4533 /* AquaTabClose_Front_Pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FC11BD9B34000826E5 /* AquaTabClose_Front_Pressed.png */; }; - 5135160625935699001E4533 /* pi.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070C11BD9B34000826E5 /* pi.png */; }; - 5135160725935699001E4533 /* AquaTabClose_Front.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FB11BD9B34000826E5 /* AquaTabClose_Front.png */; }; - 5135160825935699001E4533 /* AquaTabNew.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070111BD9B34000826E5 /* AquaTabNew.png */; }; - 5135160925935699001E4533 /* AquaTabsSeparator.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070811BD9B34000826E5 /* AquaTabsSeparator.png */; }; - 5135160A25935699001E4533 /* TabClose_Front.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071011BD9B34000826E5 /* TabClose_Front.png */; }; - 5135160B25935699001E4533 /* AquaTabNewRollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070311BD9B34000826E5 /* AquaTabNewRollover.png */; }; - 5135160C25935699001E4533 /* AquaTabsDownNonKey.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070711BD9B34000826E5 /* AquaTabsDownNonKey.png */; }; - 5135160D25935699001E4533 /* overflowImagePressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070B11BD9B34000826E5 /* overflowImagePressed.png */; }; - 5135160E25935699001E4533 /* AddTabButton.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6311C67D8A006A3386 /* AddTabButton.png */; }; - 5135160F25935699001E4533 /* AddTabButtonPushed.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */; }; - 5135161025935699001E4533 /* SequelProTabDirty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 58C4BA1316781A93004068AB /* SequelProTabDirty@2x.png */; }; - 5135161125935699001E4533 /* TabClose_Dirty.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070D11BD9B34000826E5 /* TabClose_Dirty.png */; }; - 5135161225935699001E4533 /* TabNewMetalPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071411BD9B34000826E5 /* TabNewMetalPressed.png */; }; - 5135161325935699001E4533 /* AquaTabsBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070411BD9B34000826E5 /* AquaTabsBackground.png */; }; - 5135161425935699001E4533 /* AquaTabCloseDirty_Front.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FE11BD9B34000826E5 /* AquaTabCloseDirty_Front.png */; }; - 5135161525935699001E4533 /* TabClose_Front_Pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9071111BD9B34000826E5 /* TabClose_Front_Pressed.png */; }; - 5135161625935699001E4533 /* AquaTabsSeparatorDown.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070911BD9B34000826E5 /* AquaTabsSeparatorDown.png */; }; - 5135161725935699001E4533 /* AquaTabsDownGraphite.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070611BD9B34000826E5 /* AquaTabsDownGraphite.png */; }; - 5135161825935699001E4533 /* TabClose_Dirty_Pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070E11BD9B34000826E5 /* TabClose_Dirty_Pressed.png */; }; - 5135161925935699001E4533 /* AquaTabsDown.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070511BD9B34000826E5 /* AquaTabsDown.png */; }; - 5135161A25935699001E4533 /* SequelProTabDirty.png in Resources */ = {isa = PBXBuildFile; fileRef = 580E8DB011EA772C000D8427 /* SequelProTabDirty.png */; }; - 5135161B25935699001E4533 /* AquaTabCloseDirty_Front_Pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B906FF11BD9B34000826E5 /* AquaTabCloseDirty_Front_Pressed.png */; }; - 5135161C25935699001E4533 /* AquaTabNewPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070211BD9B34000826E5 /* AquaTabNewPressed.png */; }; - 5135161D25935699001E4533 /* TabClose_Dirty_Rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070F11BD9B34000826E5 /* TabClose_Dirty_Rollover.png */; }; - 5135161E25935699001E4533 /* AddTabButtonRollover.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */; }; - 5135161F25935699001E4533 /* AquaTabCloseDirty_Front_Rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 58B9070011BD9B34000826E5 /* AquaTabCloseDirty_Front_Rollover.png */; }; - 5135162025935699001E4533 /* SequelProTabDirty_Rollover.png in Resources */ = {isa = PBXBuildFile; fileRef = 580E8DAF11EA772C000D8427 /* SequelProTabDirty_Rollover.png */; }; - 5135162125935699001E4533 /* SequelProTabDirty_Pressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 580E8DAE11EA772C000D8427 /* SequelProTabDirty_Pressed.png */; }; 515D303F25BD7DE60021CF1E /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = 515D303E25BD7DE60021CF1E /* AppCenterCrashes */; }; 515D304125BD7DE60021CF1E /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 515D304025BD7DE60021CF1E /* AppCenterAnalytics */; }; 517412302573E10C00EB6935 /* SPPrintUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 5174122F2573E10C00EB6935 /* SPPrintUtility.m */; }; @@ -905,7 +854,6 @@ 50EA92691AB246B8008D3C4F /* SPDatabaseActionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDatabaseActionTest.m; sourceTree = ""; }; 50F530511ABCF66B002F2C1A /* resetTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = resetTemplate.pdf; sourceTree = ""; }; 511B309F25ABBC6500D010E3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; - 511C466925BC768E001AA1BD /* NSTabViewItemExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSTabViewItemExtension.swift; sourceTree = ""; }; 513515D1259354BB001E4533 /* NSImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSImageExtensions.swift; sourceTree = ""; }; 5174122E2573E10C00EB6935 /* SPPrintUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPPrintUtility.h; sourceTree = ""; }; 5174122F2573E10C00EB6935 /* SPPrintUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPPrintUtility.m; sourceTree = ""; }; @@ -956,9 +904,6 @@ 51F4AFBE24B26665006144D5 /* NSAlertExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAlertExtension.swift; sourceTree = ""; }; 5806B76211A991EC00813A88 /* SPDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDocumentController.h; sourceTree = ""; }; 5806B76311A991EC00813A88 /* SPDocumentController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDocumentController.m; sourceTree = ""; }; - 580E8DAE11EA772C000D8427 /* SequelProTabDirty_Pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SequelProTabDirty_Pressed.png; sourceTree = ""; }; - 580E8DAF11EA772C000D8427 /* SequelProTabDirty_Rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SequelProTabDirty_Rollover.png; sourceTree = ""; }; - 580E8DB011EA772C000D8427 /* SequelProTabDirty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SequelProTabDirty.png; sourceTree = ""; }; 581068B51015411B0068C6E2 /* link-arrow-highlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "link-arrow-highlighted.png"; sourceTree = ""; }; 5822C9B31000DB2400DCC3D6 /* SPConnectionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPConnectionController.h; sourceTree = ""; }; 5822C9B41000DB2400DCC3D6 /* SPConnectionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPConnectionController.m; sourceTree = ""; }; @@ -1032,66 +977,10 @@ 58A137CC123ED5E6000B1B75 /* titlebarlock.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = titlebarlock.png; sourceTree = ""; }; 58A8A78F11A036C000B95749 /* SPWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPWindowController.h; sourceTree = ""; }; 58A8A79011A036C000B95749 /* SPWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPWindowController.m; sourceTree = ""; }; - 58B906FA11BD9B34000826E5 /* AdiumGradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AdiumGradient.png; sourceTree = ""; }; - 58B906FB11BD9B34000826E5 /* AquaTabClose_Front.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabClose_Front.png; sourceTree = ""; }; - 58B906FC11BD9B34000826E5 /* AquaTabClose_Front_Pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabClose_Front_Pressed.png; sourceTree = ""; }; - 58B906FD11BD9B34000826E5 /* AquaTabClose_Front_Rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabClose_Front_Rollover.png; sourceTree = ""; }; - 58B906FE11BD9B34000826E5 /* AquaTabCloseDirty_Front.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabCloseDirty_Front.png; sourceTree = ""; }; - 58B906FF11BD9B34000826E5 /* AquaTabCloseDirty_Front_Pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabCloseDirty_Front_Pressed.png; sourceTree = ""; }; - 58B9070011BD9B34000826E5 /* AquaTabCloseDirty_Front_Rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabCloseDirty_Front_Rollover.png; sourceTree = ""; }; - 58B9070111BD9B34000826E5 /* AquaTabNew.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabNew.png; sourceTree = ""; }; - 58B9070211BD9B34000826E5 /* AquaTabNewPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabNewPressed.png; sourceTree = ""; }; - 58B9070311BD9B34000826E5 /* AquaTabNewRollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabNewRollover.png; sourceTree = ""; }; - 58B9070411BD9B34000826E5 /* AquaTabsBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsBackground.png; sourceTree = ""; }; - 58B9070511BD9B34000826E5 /* AquaTabsDown.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsDown.png; sourceTree = ""; }; - 58B9070611BD9B34000826E5 /* AquaTabsDownGraphite.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsDownGraphite.png; sourceTree = ""; }; - 58B9070711BD9B34000826E5 /* AquaTabsDownNonKey.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsDownNonKey.png; sourceTree = ""; }; - 58B9070811BD9B34000826E5 /* AquaTabsSeparator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsSeparator.png; sourceTree = ""; }; - 58B9070911BD9B34000826E5 /* AquaTabsSeparatorDown.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AquaTabsSeparatorDown.png; sourceTree = ""; }; - 58B9070A11BD9B34000826E5 /* overflowImage.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overflowImage.png; sourceTree = ""; }; - 58B9070B11BD9B34000826E5 /* overflowImagePressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overflowImagePressed.png; sourceTree = ""; }; - 58B9070C11BD9B34000826E5 /* pi.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pi.png; sourceTree = ""; }; - 58B9070D11BD9B34000826E5 /* TabClose_Dirty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Dirty.png; sourceTree = ""; }; - 58B9070E11BD9B34000826E5 /* TabClose_Dirty_Pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Dirty_Pressed.png; sourceTree = ""; }; - 58B9070F11BD9B34000826E5 /* TabClose_Dirty_Rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Dirty_Rollover.png; sourceTree = ""; }; - 58B9071011BD9B34000826E5 /* TabClose_Front.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Front.png; sourceTree = ""; }; - 58B9071111BD9B34000826E5 /* TabClose_Front_Pressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Front_Pressed.png; sourceTree = ""; }; - 58B9071211BD9B34000826E5 /* TabClose_Front_Rollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabClose_Front_Rollover.png; sourceTree = ""; }; - 58B9071311BD9B34000826E5 /* TabNewMetal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabNewMetal.png; sourceTree = ""; }; - 58B9071411BD9B34000826E5 /* TabNewMetalPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabNewMetalPressed.png; sourceTree = ""; }; - 58B9071511BD9B34000826E5 /* TabNewMetalRollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TabNewMetalRollover.png; sourceTree = ""; }; - 58B9071611BD9B34000826E5 /* NSBezierPath_AMShading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSBezierPath_AMShading.h; sourceTree = ""; }; - 58B9071711BD9B34000826E5 /* NSBezierPath_AMShading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSBezierPath_AMShading.m; sourceTree = ""; }; - 58B9071811BD9B34000826E5 /* NSString_AITruncation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSString_AITruncation.h; sourceTree = ""; }; - 58B9071911BD9B34000826E5 /* NSString_AITruncation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSString_AITruncation.m; sourceTree = ""; }; - 58B9071A11BD9B34000826E5 /* PSMOverflowPopUpButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMOverflowPopUpButton.h; sourceTree = ""; }; - 58B9071B11BD9B34000826E5 /* PSMOverflowPopUpButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMOverflowPopUpButton.m; sourceTree = ""; }; - 58B9071C11BD9B34000826E5 /* PSMProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMProgressIndicator.h; sourceTree = ""; }; - 58B9071D11BD9B34000826E5 /* PSMProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMProgressIndicator.m; sourceTree = ""; }; - 58B9071E11BD9B34000826E5 /* PSMRolloverButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMRolloverButton.h; sourceTree = ""; }; - 58B9071F11BD9B34000826E5 /* PSMRolloverButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMRolloverButton.m; sourceTree = ""; }; - 58B9072011BD9B34000826E5 /* PSMTabBarCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabBarCell.h; sourceTree = ""; }; - 58B9072111BD9B34000826E5 /* PSMTabBarCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabBarCell.m; sourceTree = ""; }; - 58B9072211BD9B34000826E5 /* PSMTabBarControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabBarControl.h; sourceTree = ""; }; - 58B9072311BD9B34000826E5 /* PSMTabBarControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabBarControl.m; sourceTree = ""; }; - 58B9072411BD9B34000826E5 /* PSMTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabBarController.h; sourceTree = ""; }; - 58B9072511BD9B34000826E5 /* PSMTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabBarController.m; sourceTree = ""; }; - 58B9072611BD9B34000826E5 /* PSMTabDragAssistant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabDragAssistant.h; sourceTree = ""; }; - 58B9072711BD9B34000826E5 /* PSMTabDragAssistant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabDragAssistant.m; sourceTree = ""; }; - 58B9072811BD9B34000826E5 /* PSMTabDragView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabDragView.h; sourceTree = ""; }; - 58B9072911BD9B34000826E5 /* PSMTabDragView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabDragView.m; sourceTree = ""; }; - 58B9072A11BD9B34000826E5 /* PSMTabDragWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabDragWindow.h; sourceTree = ""; }; - 58B9072B11BD9B34000826E5 /* PSMTabDragWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabDragWindow.m; sourceTree = ""; }; - 58B9072C11BD9B34000826E5 /* PSMTabDragWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabDragWindowController.h; sourceTree = ""; }; - 58B9072D11BD9B34000826E5 /* PSMTabDragWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMTabDragWindowController.m; sourceTree = ""; }; - 58B9072E11BD9B34000826E5 /* PSMTabStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMTabStyle.h; sourceTree = ""; }; 58B9077D11BD9B64000826E5 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 58B9088711BDB7AA000826E5 /* PSMTabBar-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PSMTabBar-Info.plist"; path = "Plists/PSMTabBar-Info.plist"; sourceTree = ""; }; 58B9095B11C3A3EC000826E5 /* xibLocalizationPostprocessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = xibLocalizationPostprocessor.m; sourceTree = ""; }; 58B9096111C3A42B000826E5 /* xibLocalizationPostprocessor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = xibLocalizationPostprocessor; sourceTree = BUILT_PRODUCTS_DIR; }; - 58C4BA1116781A93004068AB /* SequelProTabDirty_Pressed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "SequelProTabDirty_Pressed@2x.png"; sourceTree = ""; }; - 58C4BA1216781A93004068AB /* SequelProTabDirty_Rollover@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "SequelProTabDirty_Rollover@2x.png"; sourceTree = ""; }; - 58C4BA1316781A93004068AB /* SequelProTabDirty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "SequelProTabDirty@2x.png"; sourceTree = ""; }; 58C56EF30F438E120035701E /* SPDataCellFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDataCellFormatter.h; sourceTree = ""; }; 58C56EF40F438E120035701E /* SPDataCellFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDataCellFormatter.m; sourceTree = ""; }; 58CDB32E0FCE138D00F8ACA3 /* SPSSHTunnel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPSSHTunnel.h; sourceTree = ""; }; @@ -1167,11 +1056,6 @@ B52460D50F8EF92300171639 /* SPTextViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPTextViewAdditions.h; sourceTree = ""; }; B52460D60F8EF92300171639 /* SPTextViewAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPTextViewAdditions.m; sourceTree = ""; }; B54F25E50FD909C400E2CF36 /* toolbar-switch-to-table-relations.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "toolbar-switch-to-table-relations.png"; sourceTree = ""; }; - B55F8E5D11C67CA0006A3386 /* PSMSequelProTabStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMSequelProTabStyle.h; sourceTree = ""; }; - B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMSequelProTabStyle.m; sourceTree = ""; }; - B55F8E6311C67D8A006A3386 /* AddTabButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButton.png; sourceTree = ""; }; - B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButtonPushed.png; sourceTree = ""; }; - B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButtonRollover.png; sourceTree = ""; }; B57747D30F7A8974003B34F9 /* SPPreferenceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPreferenceController.m; sourceTree = ""; }; B57747D50F7A8978003B34F9 /* SPPreferenceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPreferenceController.h; sourceTree = ""; }; B57747D70F7A8990003B34F9 /* SPWindowAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPWindowAdditions.h; sourceTree = ""; }; @@ -2159,7 +2043,6 @@ children = ( 17E5954E14F304000054EE08 /* QueryKit.xcodeproj */, 584D876015140D3500F24774 /* SPMySQLFramework.xcodeproj */, - 58B906F811BD9B34000826E5 /* PSMTabBar */, ); name = Frameworks; path = ..; @@ -2382,95 +2265,6 @@ name = Products; sourceTree = ""; }; - 58B906F811BD9B34000826E5 /* PSMTabBar */ = { - isa = PBXGroup; - children = ( - 58B9071611BD9B34000826E5 /* NSBezierPath_AMShading.h */, - 58B9071711BD9B34000826E5 /* NSBezierPath_AMShading.m */, - 58B9071811BD9B34000826E5 /* NSString_AITruncation.h */, - 58B9071911BD9B34000826E5 /* NSString_AITruncation.m */, - 58B9071A11BD9B34000826E5 /* PSMOverflowPopUpButton.h */, - 58B9071B11BD9B34000826E5 /* PSMOverflowPopUpButton.m */, - 58B9071C11BD9B34000826E5 /* PSMProgressIndicator.h */, - 58B9071D11BD9B34000826E5 /* PSMProgressIndicator.m */, - 58B9071E11BD9B34000826E5 /* PSMRolloverButton.h */, - 58B9071F11BD9B34000826E5 /* PSMRolloverButton.m */, - 58B9072011BD9B34000826E5 /* PSMTabBarCell.h */, - 58B9072111BD9B34000826E5 /* PSMTabBarCell.m */, - 58B9072211BD9B34000826E5 /* PSMTabBarControl.h */, - 58B9072311BD9B34000826E5 /* PSMTabBarControl.m */, - 58B9072411BD9B34000826E5 /* PSMTabBarController.h */, - 58B9072511BD9B34000826E5 /* PSMTabBarController.m */, - 58B9072611BD9B34000826E5 /* PSMTabDragAssistant.h */, - 58B9072711BD9B34000826E5 /* PSMTabDragAssistant.m */, - 58B9072811BD9B34000826E5 /* PSMTabDragView.h */, - 58B9072911BD9B34000826E5 /* PSMTabDragView.m */, - 58B9072A11BD9B34000826E5 /* PSMTabDragWindow.h */, - 58B9072B11BD9B34000826E5 /* PSMTabDragWindow.m */, - 58B9072C11BD9B34000826E5 /* PSMTabDragWindowController.h */, - 58B9072D11BD9B34000826E5 /* PSMTabDragWindowController.m */, - 58B9072E11BD9B34000826E5 /* PSMTabStyle.h */, - 58B9072F11BD9B34000826E5 /* Styles */, - 58B906F911BD9B34000826E5 /* Images */, - 511C466925BC768E001AA1BD /* NSTabViewItemExtension.swift */, - ); - name = PSMTabBar; - path = Frameworks/PSMTabBar; - sourceTree = ""; - }; - 58B906F911BD9B34000826E5 /* Images */ = { - isa = PBXGroup; - children = ( - 58B906FA11BD9B34000826E5 /* AdiumGradient.png */, - B55F8E6311C67D8A006A3386 /* AddTabButton.png */, - B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */, - B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */, - 58B906FB11BD9B34000826E5 /* AquaTabClose_Front.png */, - 58B906FC11BD9B34000826E5 /* AquaTabClose_Front_Pressed.png */, - 58B906FD11BD9B34000826E5 /* AquaTabClose_Front_Rollover.png */, - 58B906FE11BD9B34000826E5 /* AquaTabCloseDirty_Front.png */, - 58B906FF11BD9B34000826E5 /* AquaTabCloseDirty_Front_Pressed.png */, - 58B9070011BD9B34000826E5 /* AquaTabCloseDirty_Front_Rollover.png */, - 58B9070111BD9B34000826E5 /* AquaTabNew.png */, - 58B9070211BD9B34000826E5 /* AquaTabNewPressed.png */, - 58B9070311BD9B34000826E5 /* AquaTabNewRollover.png */, - 58B9070411BD9B34000826E5 /* AquaTabsBackground.png */, - 58B9070511BD9B34000826E5 /* AquaTabsDown.png */, - 58B9070611BD9B34000826E5 /* AquaTabsDownGraphite.png */, - 58B9070711BD9B34000826E5 /* AquaTabsDownNonKey.png */, - 58B9070811BD9B34000826E5 /* AquaTabsSeparator.png */, - 58B9070911BD9B34000826E5 /* AquaTabsSeparatorDown.png */, - 58B9070A11BD9B34000826E5 /* overflowImage.png */, - 58B9070B11BD9B34000826E5 /* overflowImagePressed.png */, - 58B9070C11BD9B34000826E5 /* pi.png */, - 580E8DAE11EA772C000D8427 /* SequelProTabDirty_Pressed.png */, - 58C4BA1116781A93004068AB /* SequelProTabDirty_Pressed@2x.png */, - 580E8DAF11EA772C000D8427 /* SequelProTabDirty_Rollover.png */, - 58C4BA1216781A93004068AB /* SequelProTabDirty_Rollover@2x.png */, - 580E8DB011EA772C000D8427 /* SequelProTabDirty.png */, - 58C4BA1316781A93004068AB /* SequelProTabDirty@2x.png */, - 58B9070D11BD9B34000826E5 /* TabClose_Dirty.png */, - 58B9070E11BD9B34000826E5 /* TabClose_Dirty_Pressed.png */, - 58B9070F11BD9B34000826E5 /* TabClose_Dirty_Rollover.png */, - 58B9071011BD9B34000826E5 /* TabClose_Front.png */, - 58B9071111BD9B34000826E5 /* TabClose_Front_Pressed.png */, - 58B9071211BD9B34000826E5 /* TabClose_Front_Rollover.png */, - 58B9071311BD9B34000826E5 /* TabNewMetal.png */, - 58B9071411BD9B34000826E5 /* TabNewMetalPressed.png */, - 58B9071511BD9B34000826E5 /* TabNewMetalRollover.png */, - ); - path = Images; - sourceTree = ""; - }; - 58B9072F11BD9B34000826E5 /* Styles */ = { - isa = PBXGroup; - children = ( - B55F8E5D11C67CA0006A3386 /* PSMSequelProTabStyle.h */, - B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */, - ); - path = Styles; - sourceTree = ""; - }; 58B909A111C3B8EC000826E5 /* Localization */ = { isa = PBXGroup; children = ( @@ -2780,23 +2574,17 @@ files = ( 51CD0BF8258D06D8009E2484 /* DatabaseProcessList.xib in Resources */, 17E641D10EF02036001BC333 /* grabber-horizontal.png in Resources */, - 5135161E25935699001E4533 /* AddTabButtonRollover.png in Resources */, - 5135160725935699001E4533 /* AquaTabClose_Front.png in Resources */, 17E641D20EF02036001BC333 /* grabber-vertical.png in Resources */, 51CD0BE5258D06D8009E2484 /* Navigator.xib in Resources */, 17E641F20EF02036001BC333 /* toolbar-switch-to-structure.png in Resources */, 17E641F30EF02036001BC333 /* toolbar-switch-to-table-info.png in Resources */, 1A6447992588CD9200927DB3 /* Credits.rtf in Resources */, 8831EFC9224016E000D10172 /* button_edit_mode_selectedTemplate.pdf in Resources */, - 5135162025935699001E4533 /* SequelProTabDirty_Rollover.png in Resources */, - 5135160925935699001E4533 /* AquaTabsSeparator.png in Resources */, 17E641FC0EF02088001BC333 /* sequel-pro.scriptSuite in Resources */, 17E641FD0EF02088001BC333 /* sequel-pro.scriptTerminology in Resources */, 51CD0BF9258D06D8009E2484 /* BundleHTMLOutput.xib in Resources */, 51CD0BDC258D06D8009E2484 /* PrintAccessory.xib in Resources */, 51CD0BEC258D06D8009E2484 /* ProgressIndicatorLayer.xib in Resources */, - 5135160E25935699001E4533 /* AddTabButton.png in Resources */, - 5135161D25935699001E4533 /* TabClose_Dirty_Rollover.png in Resources */, B5E2C5FA0F2353B5007446E0 /* table-property.png in Resources */, 51CD0BDD258D06D8009E2484 /* DataMigrationDialog.xib in Resources */, B57748420F7A8B57003B34F9 /* database.png in Resources */, @@ -2807,31 +2595,21 @@ 384582C40FB95FF800DDACB6 /* func-small.png in Resources */, 384582C70FB9603600DDACB6 /* proc-small.png in Resources */, 51CD0BEE258D06D8009E2484 /* UserManagerView.xib in Resources */, - 5135160025935699001E4533 /* TabNewMetal.png in Resources */, - 5135161325935699001E4533 /* AquaTabsBackground.png in Resources */, - 5135161825935699001E4533 /* TabClose_Dirty_Pressed.png in Resources */, 8831EFCE2240175400D10172 /* button_paginationTemplate.pdf in Resources */, - 5135161525935699001E4533 /* TabClose_Front_Pressed.png in Resources */, 177E792E0FCB54EC00E9E122 /* database-small.png in Resources */, 8831EFC22240166D00D10172 /* button_select_noneTemplate.pdf in Resources */, 51CD0BEB258D06D8009E2484 /* ConnectionErrorDialog.xib in Resources */, 1A6D28FE25DD8018007509F1 /* ProgressWindowController.storyboard in Resources */, 51CD0BF1258D06D8009E2484 /* ContentFilterManager.xib in Resources */, 177E792F0FCB54EC00E9E122 /* dummy-small.png in Resources */, - 513515FE25935699001E4533 /* SequelProTabDirty_Rollover@2x.png in Resources */, 51CD0BE3258D06D8009E2484 /* DBView.xib in Resources */, B54F25E60FD909C400E2CF36 /* toolbar-switch-to-table-relations.png in Resources */, - 5135160D25935699001E4533 /* overflowImagePressed.png in Resources */, 8831EFB0224013AF00D10172 /* button_refreshTemplate.pdf in Resources */, - 5135160125935699001E4533 /* TabClose_Front_Rollover.png in Resources */, 3E242D4F20FEB44D0015470D /* button_bar_spacer_dark.png in Resources */, 588B2CC80FE5641E00EC5FC0 /* ssh-connected.png in Resources */, 588B2CC90FE5641E00EC5FC0 /* ssh-connecting.png in Resources */, - 5135160A25935699001E4533 /* TabClose_Front.png in Resources */, - 5135162125935699001E4533 /* SequelProTabDirty_Pressed.png in Resources */, 588B2CCA0FE5641E00EC5FC0 /* ssh-disconnected.png in Resources */, 51CD0BDF258D06D8009E2484 /* FilterTableWindow.xib in Resources */, - 5135160825935699001E4533 /* AquaTabNew.png in Resources */, 58D2E22E101222870063EF1D /* link-arrow-clicked.png in Resources */, 58D2E22F101222870063EF1D /* link-arrow-highlighted-clicked.png in Resources */, 58D2E230101222870063EF1D /* link-arrow.png in Resources */, @@ -2845,7 +2623,6 @@ 51CD0BF6258D06D8009E2484 /* ConnectionView.xib in Resources */, 17E0937E114AE154007FC1B4 /* SPTableInfoPrintTemplate.html in Resources */, B51D6B9E114C310C0074704E /* toolbar-switch-to-table-triggers.png in Resources */, - 5135161225935699001E4533 /* TabNewMetalPressed.png in Resources */, 8831EFBA2240154A00D10172 /* button_rightTemplate.pdf in Resources */, 51CD0BE0258D06D8009E2484 /* FieldEditorSheet.xib in Resources */, 17DD52B7115071D0007D8950 /* SPPrintTemplate.html in Resources */, @@ -2856,18 +2633,12 @@ 8831EFC12240166D00D10172 /* button_select_allTemplate.pdf in Resources */, 58A137CD123ED5E6000B1B75 /* titlebarlock.png in Resources */, 51CD0BEF258D06D8009E2484 /* ExportDialog.xib in Resources */, - 5135161F25935699001E4533 /* AquaTabCloseDirty_Front_Rollover.png in Resources */, BC09D7DE12A786FB0030DB64 /* cancel-clicked-highlighted.png in Resources */, 8831EFAC2240131500D10172 /* button_editTemplate.pdf in Resources */, BC09D7DF12A786FB0030DB64 /* cancel-clicked.png in Resources */, - 5135161925935699001E4533 /* AquaTabsDown.png in Resources */, - 5135161A25935699001E4533 /* SequelProTabDirty.png in Resources */, - 5135160325935699001E4533 /* AquaTabClose_Front_Rollover.png in Resources */, BC09D7E012A786FB0030DB64 /* cancel-highlighted.png in Resources */, - 5135161125935699001E4533 /* TabClose_Dirty.png in Resources */, BC09D7E112A786FB0030DB64 /* cancel-hovered-highlighted.png in Resources */, BC09D7E212A786FB0030DB64 /* cancel-hovered.png in Resources */, - 5135161C25935699001E4533 /* AquaTabNewPressed.png in Resources */, BC09D7E312A786FB0030DB64 /* cancel.png in Resources */, 58F48AA3161D03C6008536A1 /* quick-connect-icon.pdf in Resources */, 58F48B2E161D08C0008536A1 /* quick-connect-icon-white.pdf in Resources */, @@ -2880,16 +2651,12 @@ 5843DA6F161FA35600EAA6D1 /* key-icon@2x.png in Resources */, 51CD0BF5258D06D8009E2484 /* QueryFavoriteManager.xib in Resources */, 8831EFBE2240159E00D10172 /* button_pane_showTemplate.pdf in Resources */, - 5135160C25935699001E4533 /* AquaTabsDownNonKey.png in Resources */, 51CD0BE9258D06D8009E2484 /* Console.xib in Resources */, 8831EFB22240143600D10172 /* button_bar_handleTemplate.pdf in Resources */, - 513515FD25935699001E4533 /* overflowImage.png in Resources */, C9F92710162D38D70051CB2E /* toolbar-switch-to-table-info@2x.png in Resources */, C9F92712162D39E60051CB2E /* toolbar-switch-to-browse.png in Resources */, 51CD0BE2258D06D8009E2484 /* IndexesView.xib in Resources */, - 5135160625935699001E4533 /* pi.png in Resources */, C9F92714162D39FE0051CB2E /* toolbar-switch-to-browse@2x.png in Resources */, - 5135160B25935699001E4533 /* AquaTabNewRollover.png in Resources */, 51CD0BE8258D06D8009E2484 /* MainMenu.xib in Resources */, 51A709392565B99F001F1D2F /* Images.xcassets in Resources */, 51CD0BE7258D06D8009E2484 /* ImportAccessory.xib in Resources */, @@ -2897,16 +2664,12 @@ C9AD7C7B1676158C00234EEE /* toolbar-switch-to-sql.png in Resources */, C9AD7C7C1676158C00234EEE /* toolbar-switch-to-sql@2x.png in Resources */, 8831EFB4224014C700D10172 /* button_clearTemplate.pdf in Resources */, - 5135160525935699001E4533 /* AquaTabClose_Front_Pressed.png in Resources */, - 513515FF25935699001E4533 /* AdiumGradient.png in Resources */, C9C994411678A439001F5DA8 /* button_bar_spacer.png in Resources */, 8831EFAE2240135400D10172 /* button_duplicateTemplate.pdf in Resources */, C9C994491678B3E6001F5DA8 /* table-small-square.png in Resources */, C9C9944A1678B3E6001F5DA8 /* table-small-square@2x.png in Resources */, 964908C8249A77D00052FC4A /* ssh_config in Resources */, - 5135161725935699001E4533 /* AquaTabsDownGraphite.png in Resources */, 8831EFCA224016E000D10172 /* button_edit_modeTemplate.pdf in Resources */, - 5135160F25935699001E4533 /* AddTabButtonPushed.png in Resources */, C9C9944D1678BCFA001F5DA8 /* table-small.png in Resources */, C9C9944E1678BCFA001F5DA8 /* table-small@2x.png in Resources */, 582E939D168296F3003459FD /* link-arrow-clicked@2x.png in Resources */, @@ -2916,7 +2679,6 @@ 582E939F168296F3003459FD /* link-arrow-highlighted@2x.png in Resources */, 582E93A0168296F3003459FD /* link-arrow@2x.png in Resources */, 51CD0BDE258D06D8009E2484 /* Preferences.xib in Resources */, - 5135161B25935699001E4533 /* AquaTabCloseDirty_Front_Pressed.png in Resources */, 8831EFB62240150A00D10172 /* button_add_folderTemplate.pdf in Resources */, 582E940E1682A2AD003459FD /* button_bar_spacer@2x.png in Resources */, 50F530521ABCF66B002F2C1A /* resetTemplate.pdf in Resources */, @@ -2931,18 +2693,13 @@ 582E945016837AA9003459FD /* network-small.png in Resources */, 582E947016837DB2003459FD /* showconsole.png in Resources */, 582E9483168380D6003459FD /* sync_arrows_01.png in Resources */, - 5135161025935699001E4533 /* SequelProTabDirty@2x.png in Resources */, 582E9484168380D6003459FD /* sync_arrows_02.png in Resources */, - 5135161625935699001E4533 /* AquaTabsSeparatorDown.png in Resources */, 582E9485168380D6003459FD /* sync_arrows_03.png in Resources */, 582E9486168380D6003459FD /* sync_arrows_04.png in Resources */, 51CD0BF2258D06D8009E2484 /* EncodingPopupView.xib in Resources */, - 5135160425935699001E4533 /* TabNewMetalRollover.png in Resources */, 51CD0BEA258D06D8009E2484 /* DatabaseServerVariables.xib in Resources */, 582E9487168380D6003459FD /* sync_arrows_05.png in Resources */, - 5135161425935699001E4533 /* AquaTabCloseDirty_Front.png in Resources */, 582E9488168380D6003459FD /* sync_arrows_06.png in Resources */, - 5135160225935699001E4533 /* SequelProTabDirty_Pressed@2x.png in Resources */, 582E948F168383F0003459FD /* table-view-small-square.png in Resources */, 582E9490168383F0003459FD /* table-view-small.png in Resources */, 582E94A816839AD5003459FD /* toolbar-preferences-autoupdate.png in Resources */, @@ -3078,9 +2835,7 @@ 507FF1121BBCC57600104523 /* SPFunctions.m in Sources */, 5193502F2567D2FB001272B5 /* CollectionExtension.swift in Sources */, 17E641590EF01EF6001BC333 /* SPTableContent.m in Sources */, - 513515EC2593568B001E4533 /* NSString_AITruncation.m in Sources */, 17E6415A0EF01EF6001BC333 /* SPDatabaseDocument.m in Sources */, - 513515EB2593568B001E4533 /* NSBezierPath_AMShading.m in Sources */, 17E6415B0EF01EF6001BC333 /* SPDataImport.m in Sources */, 17E6415C0EF01EF6001BC333 /* SPTableStructure.m in Sources */, 1A8B582A25EEE15900DFC54A /* ByteCountFormatterExtension.swift in Sources */, @@ -3089,10 +2844,8 @@ 17E641640EF01F15001BC333 /* SPTableInfo.m in Sources */, 17E641650EF01F15001BC333 /* SPTablesList.m in Sources */, 17E6416C0EF01F37001BC333 /* ImageAndTextCell.m in Sources */, - 513515EA2593568B001E4533 /* PSMTabDragWindowController.m in Sources */, 17E641750EF01F80001BC333 /* SPKeychain.m in Sources */, 17E641830EF01FA8001BC333 /* SPImageView.m in Sources */, - 513515E52593568B001E4533 /* PSMTabDragAssistant.m in Sources */, 17E641840EF01FA8001BC333 /* SPTextView.m in Sources */, 58FEF16D0F23D66600518E8E /* SPSQLParser.m in Sources */, 1789343C0F30C1DD0097539A /* SPStringAdditions.m in Sources */, @@ -3151,10 +2904,8 @@ BCA6271C1031B9D40047E5D5 /* SPTooltip.m in Sources */, 58DA8863103E15B5000B98DF /* SPLogger.m in Sources */, BC01BCCF104024BE006BDEE7 /* SPEncodingPopupAccessory.m in Sources */, - 513515E42593568B001E4533 /* PSMProgressIndicator.m in Sources */, 3876E15D1CC0BA0300D85154 /* SPTableFooterPopUpButtonCell.m in Sources */, 51BC14F825BE135500F1CDC9 /* SPWindowController.swift in Sources */, - 513515E92593568B001E4533 /* PSMTabDragWindow.m in Sources */, 173C4366104455E0001F3A30 /* SPQueryFavoriteManager.m in Sources */, 173C44D81044A6B0001F3A30 /* SPOutlineView.m in Sources */, 500C1F921BFB5F9F0095DC7F /* SPPrivilegesMO.m in Sources */, @@ -3176,7 +2927,6 @@ 1A70BC6625EF4243004BB992 /* ReportExceptionApplication.m in Sources */, 5089B0271BE714E300E226CD /* SPIdMenu.m in Sources */, 17CC97F310B4ABE90034CD7A /* SPAboutController.m in Sources */, - 513515ED2593568B001E4533 /* PSMTabBarController.m in Sources */, 51C4626D254ED02500F63E70 /* UserDefaultsExtension.swift in Sources */, 5870868410FA3E9C00D58E1C /* SPDataStorage.m in Sources */, 29FA88231114619E00D1AF3D /* SPTableTriggers.m in Sources */, @@ -3209,7 +2959,6 @@ BC32F242121D66260067305E /* SPFileManagerAdditions.m in Sources */, 17A20AC6124F9B110095CEFB /* SPServerSupport.m in Sources */, BC2898F3125F4488001B50E1 /* SPGeometryDataView.m in Sources */, - 513515F425935691001E4533 /* PSMSequelProTabStyle.m in Sources */, 17D38F701279E23A00672B13 /* SPTableFieldValidation.m in Sources */, 17D390C8127B65AF00672B13 /* SPGeneralPreferencePane.m in Sources */, 1A9D83A425514E740024B563 /* DateComponentsFormatterExtension.swift in Sources */, @@ -3225,9 +2974,7 @@ 17D3C22212859E070047709F /* SPFavoriteNode.m in Sources */, 506CE9311A311C6C0039F736 /* SPRuleFilterController.m in Sources */, 17D3C66E128AD4710047709F /* SPFavoritesController.m in Sources */, - 513515E62593568B001E4533 /* PSMOverflowPopUpButton.m in Sources */, 17D3C671128AD8160047709F /* SPSingleton.m in Sources */, - 513515E72593568B001E4533 /* PSMTabBarControl.m in Sources */, 17D3C6D3128B1C900047709F /* SPFavoritesOutlineView.m in Sources */, 50D3C3521A77135F00B5429C /* SPParserUtils.c in Sources */, 1A8B53572584520800526DED /* SPURLAdditions.m in Sources */, @@ -3238,12 +2985,10 @@ BC77C5E4129AA69E009AD832 /* SPBundleHTMLOutputController.m in Sources */, BC5750D512A6233900911BA2 /* SPActivityTextFieldCell.m in Sources */, BC0ED3DA12A9196C00088461 /* SPChooseMenuItemDialog.m in Sources */, - 511C466A25BC768E001AA1BD /* NSTabViewItemExtension.swift in Sources */, 51BC150625BE13C400F1CDC9 /* NSViewExtension.swift in Sources */, 583CA21512EC8B2200C9E763 /* SPWindow.m in Sources */, 1A9EB9AE25651F5000FE60FF /* SQLiteHistoryManager.swift in Sources */, 582F02311370B52600B30621 /* SPExportFileNameTokenObject.m in Sources */, - 513515EE2593568B001E4533 /* PSMTabDragView.m in Sources */, 500DA4BC1BF0CD57000773FE /* SPScreenAdditions.m in Sources */, 584D878B15140FEB00F24774 /* SPObjectAdditions.m in Sources */, 584D87921514101E00F24774 /* SPDatabaseStructure.m in Sources */, @@ -3256,7 +3001,6 @@ 1798F1951550181B004B0AB8 /* SPGroupNode.m in Sources */, 1798F19815501838004B0AB8 /* SPMutableArrayAdditions.m in Sources */, 1A1EE94A2551185D0056FECD /* DateFormatterExtension.swift in Sources */, - 513515EF2593568B001E4533 /* PSMRolloverButton.m in Sources */, 1798F19B1550185B004B0AB8 /* SPTreeNode.m in Sources */, 17D5B49E1553059F00EF3BB3 /* SPViewCopy.m in Sources */, 176E14D115570FE300FAF326 /* SPBundleCommandRunner.m in Sources */, @@ -3268,7 +3012,6 @@ 501B1D181728A3DA0017C92E /* SPCharsetCollationHelper.m in Sources */, 50E217B318174246009D3580 /* SPColorSelectorView.m in Sources */, 50E217B618174280009D3580 /* SPFavoriteColorSupport.m in Sources */, - 513515E82593568B001E4533 /* PSMTabBarCell.m in Sources */, 1A6377D4259B414400B1E96D /* SecureBookmark.swift in Sources */, 1A564F74237E2E4958CA593A /* SPPillAttachmentCell.m in Sources */, 9BE76F2886901784E4FD2321 /* SPFilterTableController.m in Sources */, From 301f18fe42e90adef7a6f2988d52269acd823a62 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sun, 7 Mar 2021 21:30:18 +0100 Subject: [PATCH 03/41] Setup properly db view --- Interfaces/MainWindow.xib | 29 +++++++++ .../MainViewControllers/SPDatabaseDocument.h | 2 +- Source/Controllers/SPAppController.m | 13 ++-- .../Controllers/Window/SPWindowController.m | 61 ++++++++----------- sequel-ace.xcodeproj/project.pbxproj | 4 ++ 5 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 Interfaces/MainWindow.xib diff --git a/Interfaces/MainWindow.xib b/Interfaces/MainWindow.xib new file mode 100644 index 000000000..29ad4f328 --- /dev/null +++ b/Interfaces/MainWindow.xib @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 1d92209e4..be403c344 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -64,7 +64,7 @@ /** * The SPDatabaseDocument class controls the primary database view window. */ -@interface SPDatabaseDocument : NSViewController +@interface SPDatabaseDocument : NSObject { // IBOutlets IBOutlet SPTablesList *tablesListInstance; diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 029624592..0c53224f1 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -646,7 +646,7 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { // Loop through each defined window in reversed order to reconstruct the last active window for (NSDictionary *window in [[[spfs objectForKey:@"windows"] reverseObjectEnumerator] allObjects]) { // Create a new window controller, and set up a new connection view within it. - SPWindowController *newWindowController = [[SPWindowController alloc] init]; + SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; [newWindowController showWindow:self]; [self.windowControllers addObject:newWindowController]; NSWindow *newWindow = [newWindowController window]; @@ -1530,15 +1530,14 @@ - (SPWindowController *)newWindowController { 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] init]; -// [newWindowController showWindow:self]; + SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; newWindowController.delegate = self; NSWindow *newWindow = [newWindowController window]; // 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; + 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 @@ -1546,14 +1545,14 @@ - (SPWindowController *)newWindowController { BOOL usedAutosave = [newWindow setFrameAutosaveName:@"DBView"]; if (!usedAutosave) { -// [newWindow setFrameUsingName:@"DBView"]; + [newWindow setFrameUsingName:@"DBView"]; } // Add the connection view [newWindowController addNewConnection]; // Cascade according to the statically stored cascade location. -// cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; + cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; // Set the window controller as the window's delegate [newWindow setDelegate:newWindowController]; diff --git a/Source/Controllers/Window/SPWindowController.m b/Source/Controllers/Window/SPWindowController.m index 67ee26ea5..c7af8008d 100644 --- a/Source/Controllers/Window/SPWindowController.m +++ b/Source/Controllers/Window/SPWindowController.m @@ -51,45 +51,34 @@ @implementation SPWindowController #pragma mark - #pragma mark Initialisation -- (instancetype)init { - SPWindow *newWindow = [[SPWindow alloc] init]; - [newWindow setContentMinSize:NSMakeSize(800, 400)]; - [newWindow setMinSize:NSMakeSize(800, 400)]; - if (self = [super initWithWindow:newWindow]) { - - [self setupAppearance]; - [self setupConstraints]; - - [self _switchOutSelectedTableDocument:nil]; - - [newWindow setCollectionBehavior:[newWindow collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; - - // Disable automatic cascading - this occurs before the size is set, so let the app - // controller apply cascading after frame autosaving. - [self setShouldCascadeWindows:NO]; - - // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. - NSMenu *mainMenu = [NSApp mainMenu]; - _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; - _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; - - // Because we are a document-based app we automatically adopt window restoration on 10.7+. - // However that causes a race condition with our own window setup code. - // Remove this when we actually support restoration. - if ([newWindow respondsToSelector:@selector(setRestorable:)]) { - [newWindow setRestorable:NO]; - } - newWindow.autorecalculatesKeyViewLoop = NO; - } - return self; -} - (void)awakeFromNib { [super awakeFromNib]; -} -- (void)windowDidLoad { - [super windowDidLoad]; + NSWindow *newWindow = [self window]; + + [self setupAppearance]; + [self setupConstraints]; + + [self _switchOutSelectedTableDocument:nil]; + + [newWindow setCollectionBehavior:[newWindow collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; + + // Disable automatic cascading - this occurs before the size is set, so let the app + // controller apply cascading after frame autosaving. + [self setShouldCascadeWindows:NO]; + + // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. + NSMenu *mainMenu = [NSApp mainMenu]; + _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; + _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; + + // Because we are a document-based app we automatically adopt window restoration on 10.7+. + // However that causes a race condition with our own window setup code. + // Remove this when we actually support restoration. + if ([newWindow respondsToSelector:@selector(setRestorable:)]) { + [newWindow setRestorable:NO]; + } } #pragma mark - @@ -100,8 +89,8 @@ - (SPDatabaseDocument *)addNewConnection // Create a new database connection view SPDatabaseDocument *databaseDocument = [[SPDatabaseDocument alloc] initWithWindowController:self]; self.selectedTableDocument = databaseDocument; - self.window.contentView.autoresizesSubviews = YES; [self.window.contentView addSubview:[databaseDocument databaseView]]; + [[databaseDocument databaseView] setFrame:self.window.contentView.frame]; // Tell the new database connection view to set up the window and update titles [databaseDocument didBecomeActiveTabInWindow]; diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index 2c4bf06e6..cb1c0c084 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -275,6 +275,7 @@ 51CD0BF9258D06D8009E2484 /* BundleHTMLOutput.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51CD0BDB258D06D8009E2484 /* BundleHTMLOutput.xib */; }; 51D9527625AE2B5300574BEB /* FMDB in Frameworks */ = {isa = PBXBuildFile; productRef = 51D9527525AE2B5300574BEB /* FMDB */; }; 51DCBEF0257134190098E303 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 38C613721C8977E600B3B6EF /* libz.tbd */; }; + 51F41FBA25F56A5900594BA5 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51F41FB625F56A5900594BA5 /* MainWindow.xib */; }; 51F4AFBF24B26665006144D5 /* NSAlertExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F4AFBE24B26665006144D5 /* NSAlertExtension.swift */; }; 5806B76411A991EC00813A88 /* SPDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5806B76311A991EC00813A88 /* SPDocumentController.m */; }; 581068B61015411B0068C6E2 /* link-arrow-highlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 581068B51015411B0068C6E2 /* link-arrow-highlighted.png */; }; @@ -900,6 +901,7 @@ 51CD0BD9258D06D8009E2484 /* AboutPanel.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AboutPanel.xib; sourceTree = ""; }; 51CD0BDA258D06D8009E2484 /* DatabaseProcessList.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DatabaseProcessList.xib; sourceTree = ""; }; 51CD0BDB258D06D8009E2484 /* BundleHTMLOutput.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BundleHTMLOutput.xib; sourceTree = ""; }; + 51F41FB625F56A5900594BA5 /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 51F4AFBD24B26665006144D5 /* Sequel-Ace-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sequel-Ace-Bridging-Header.h"; sourceTree = ""; }; 51F4AFBE24B26665006144D5 /* NSAlertExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAlertExtension.swift; sourceTree = ""; }; 5806B76211A991EC00813A88 /* SPDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDocumentController.h; sourceTree = ""; }; @@ -1968,6 +1970,7 @@ 17E642050EF020A3001BC333 /* Interfaces */ = { isa = PBXGroup; children = ( + 51F41FB625F56A5900594BA5 /* MainWindow.xib */, 51CD0BD9258D06D8009E2484 /* AboutPanel.xib */, 51CD0BD2258D06D8009E2484 /* BundleEditor.xib */, 51CD0BDB258D06D8009E2484 /* BundleHTMLOutput.xib */, @@ -2633,6 +2636,7 @@ 8831EFC12240166D00D10172 /* button_select_allTemplate.pdf in Resources */, 58A137CD123ED5E6000B1B75 /* titlebarlock.png in Resources */, 51CD0BEF258D06D8009E2484 /* ExportDialog.xib in Resources */, + 51F41FBA25F56A5900594BA5 /* MainWindow.xib in Resources */, BC09D7DE12A786FB0030DB64 /* cancel-clicked-highlighted.png in Resources */, 8831EFAC2240131500D10172 /* button_editTemplate.pdf in Resources */, BC09D7DF12A786FB0030DB64 /* cancel-clicked.png in Resources */, From 45072df47af84437923278b8e33575eeba295f05 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sun, 7 Mar 2021 22:35:48 +0100 Subject: [PATCH 04/41] Convert SPWindowController to Swift, disable tabbing --- .../BundleSupport/SPBundleCommandRunner.m | 1 - Source/Controllers/DataImport/SPDataImport.m | 1 - .../ConnectionView/SPConnectionController.m | 1 - .../MainViewControllers/SPDatabaseDocument.m | 4 +- Source/Controllers/SPAppController.m | 40 ++-- .../SubviewControllers/SPTablesList.m | 7 +- .../Controllers/Window/SPWindowController.h | 52 ----- .../Controllers/Window/SPWindowController.m | 210 ------------------ .../Window/SPWindowController.swift | 55 +++-- .../CategoryAdditions/SPTextViewAdditions.m | 1 - .../CategoryAdditions/SPWindowAdditions.m | 3 +- Source/Sequel-Ace-Bridging-Header.h | 1 - Source/Views/SPWindow.m | 1 - Source/Views/TableViews/SPTableView.m | 3 +- sequel-ace.xcodeproj/project.pbxproj | 6 - 15 files changed, 50 insertions(+), 336 deletions(-) delete mode 100644 Source/Controllers/Window/SPWindowController.h delete mode 100644 Source/Controllers/Window/SPWindowController.m diff --git a/Source/Controllers/BundleSupport/SPBundleCommandRunner.m b/Source/Controllers/BundleSupport/SPBundleCommandRunner.m index b86925188..59a8a63cd 100644 --- a/Source/Controllers/BundleSupport/SPBundleCommandRunner.m +++ b/Source/Controllers/BundleSupport/SPBundleCommandRunner.m @@ -31,7 +31,6 @@ #import "SPBundleCommandRunner.h" #import "SPDatabaseDocument.h" #import "SPAppController.h" -#import "SPWindowController.h" #import "sequel-ace-Swift.h" #import diff --git a/Source/Controllers/DataImport/SPDataImport.m b/Source/Controllers/DataImport/SPDataImport.m index 651a09617..8a7783f69 100644 --- a/Source/Controllers/DataImport/SPDataImport.m +++ b/Source/Controllers/DataImport/SPDataImport.m @@ -46,7 +46,6 @@ #import "SPFunctions.h" #import "SPQueryController.h" #import "SPConstants.h" -#import "SPWindowController.h" #import diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 464f1282f..9f731a67c 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -46,7 +46,6 @@ #import "SPThreadAdditions.h" #import "SPFavoriteColorSupport.h" #import "SPNamedNode.h" -#import "SPWindowController.h" #import "SPFavoritesOutlineView.h" #import "SPCategoryAdditions.h" #import "SPFavoriteTextFieldCell.h" diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 1f67166af..62ba0ce56 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -42,7 +42,6 @@ #import "SPExportController.h" #import "SPSplitView.h" #import "SPQueryController.h" -#import "SPWindowController.h" #import "SPNavigatorController.h" #import "SPSQLParser.h" #import "SPTableData.h" @@ -262,6 +261,7 @@ - (void)awakeFromNib // Set collapsible behaviour on the table list so collapsing behaviour handles resize issus [contentViewSplitter setCollapsibleSubviewIndex:0]; + [contentViewSplitter setMaxSize:200.0f ofSubviewAtIndex:0]; // Set a minimum size on both text views on the table info page [tableInfoSplitView setMinSize:20 ofSubviewAtIndex:0]; @@ -3215,7 +3215,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB - (IBAction)openDatabaseInNewTab:(id)sender { // Add a new tab to the window - [self.parentWindowController addNewConnection]; +// [self.parentWindowController addNewConnection]; // Get the current state NSDictionary *allStateDetails = @{ diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 0c53224f1..18a0e4828 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -36,7 +36,6 @@ #import "SPAboutController.h" #import "SPDataImport.h" #import "SPEncodingPopupAccessory.h" -#import "SPWindowController.h" #import "SPPreferencesUpgrade.h" #import "SPBundleEditorController.h" #import "SPTooltip.h" @@ -696,10 +695,9 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { if(newWindowController) { if ([[newWindowController window] isMiniaturized]) [[newWindowController window] deminiaturize:self]; - SPDatabaseDocument *newConnection = [newWindowController addNewConnection]; - [newConnection setIsSavedInBundle:isBundleFile]; - if (![newConnection setStateFromConnectionFile:fileName]) { + [newWindowController.selectedTableDocument setIsSavedInBundle:isBundleFile]; + if (![newWindowController.selectedTableDocument setStateFromConnectionFile:fileName]) { break; } } @@ -1548,9 +1546,6 @@ - (SPWindowController *)newWindowController { [newWindow setFrameUsingName:@"DBView"]; } - // Add the connection view - [newWindowController addNewConnection]; - // Cascade according to the statically stored cascade location. cascadeLocation = [newWindow cascadeTopLeftFromPoint:cascadeLocation]; @@ -1575,10 +1570,10 @@ - (IBAction)newTab:(id)sender { if (!self.activeWindowController) { [self newWindowController]; } else { - if ([[self.activeWindowController window] isMiniaturized]) { - [[self.activeWindowController window] deminiaturize:self]; - } - [self.activeWindowController addNewConnection]; +// if ([[self.activeWindowController window] isMiniaturized]) { +// [[self.activeWindowController window] deminiaturize:self]; +// } +// [self.activeWindowController addNewConnection]; } } @@ -1592,12 +1587,12 @@ - (SPDatabaseDocument *)createNewDatabaseDocument { databaseDocument = [self.activeWindowController selectedTableDocument]; } // Open the spf file in a new tab if the tab bar is visible - else { - if ([[self.activeWindowController window] isMiniaturized]) { - [[self.activeWindowController window] deminiaturize:self]; - } - databaseDocument = [self.activeWindowController addNewConnection]; - } +// else { +// if ([[self.activeWindowController window] isMiniaturized]) { +// [[self.activeWindowController window] deminiaturize:self]; +// } +// databaseDocument = [self.activeWindowController addNewConnection]; +// } return databaseDocument; } @@ -1631,8 +1626,6 @@ - (IBAction)duplicateTab:(id)sender [[self.activeWindowController window] deminiaturize:self]; } - SPDatabaseDocument *newConnection = [self.activeWindowController addNewConnection]; - // Get the state of the previously-frontmost document NSDictionary *allStateDetails = @{ @"connection" : @YES, @@ -1647,8 +1640,9 @@ - (IBAction)duplicateTab:(id)sender // Ensure it's set to autoconnect [frontState setObject:@YES forKey:@"auto_connect"]; - // Set the connection on the new tab - [newConnection setState:frontState]; +// SPDatabaseDocument *newConnection = [self.activeWindowController addNewConnection]; +// // Set the connection on the new tab +// [newConnection setState:frontState]; } #pragma mark - NSWindowDelegate @@ -1793,10 +1787,6 @@ - (void)rebuildMenus{ #pragma mark - SPWindowControllerDelegate -- (void)windowControllerDidCreateNewWindowController:(SPWindowController *)newWindowController { - [self.windowControllers addObject:newWindowController]; -} - - (void)windowControllerDidClose:(SPWindowController *)windowController { [self.windowControllers removeObject:windowController]; } diff --git a/Source/Controllers/SubviewControllers/SPTablesList.m b/Source/Controllers/SubviewControllers/SPTablesList.m index 921f0fabe..a4591e846 100644 --- a/Source/Controllers/SubviewControllers/SPTablesList.m +++ b/Source/Controllers/SubviewControllers/SPTablesList.m @@ -45,7 +45,6 @@ #import "SPNavigatorController.h" #import "SPHistoryController.h" #import "SPServerSupport.h" -#import "SPWindowController.h" #import "SPAppController.h" #import "SPSplitView.h" #import "SPThreadAdditions.h" @@ -717,9 +716,9 @@ - (IBAction)truncateTable:(id)sender { - (IBAction)openTableInNewTab:(id)sender { // Add a new tab to the window - [[tableDocumentInstance parentWindowController] addNewConnection]; - - [self _duplicateConnectionToFrontTab]; +// [[tableDocumentInstance parentWindowController] addNewConnection]; +// +// [self _duplicateConnectionToFrontTab]; } - (void)_duplicateConnectionToFrontTab diff --git a/Source/Controllers/Window/SPWindowController.h b/Source/Controllers/Window/SPWindowController.h deleted file mode 100644 index b37f3220c..000000000 --- a/Source/Controllers/Window/SPWindowController.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// SPWindowController.h -// sequel-pro -// -// Created by Rowan Beentje on May 16, 2010. -// Copyright (c) 2010 Rowan Beentje. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -@import AppKit; - -@class SPDatabaseDocument; -@protocol SPWindowControllerDelegate; - -@interface SPWindowController : NSWindowController - -@property (nonatomic, strong) NSMenuItem *closeWindowMenuItem; -@property (nonatomic, strong) NSMenuItem *closeTabMenuItem; -@property (nonatomic, weak) id delegate; -@property (readonly, strong) SPDatabaseDocument *selectedTableDocument; - -- (SPDatabaseDocument *)addNewConnection; - -@end - -@protocol SPWindowControllerDelegate - -- (void)windowControllerDidCreateNewWindowController:(SPWindowController *)newWindowController; -- (void)windowControllerDidClose:(SPWindowController *)windowController; - -@end diff --git a/Source/Controllers/Window/SPWindowController.m b/Source/Controllers/Window/SPWindowController.m deleted file mode 100644 index c7af8008d..000000000 --- a/Source/Controllers/Window/SPWindowController.m +++ /dev/null @@ -1,210 +0,0 @@ -// -// SPWindowController.m -// sequel-pro -// -// Created by Rowan Beentje on May 16, 2010. -// Copyright (c) 2010 Rowan Beentje. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// -// More info at - -#import "SPWindowController.h" -#import "SPDatabaseDocument.h" -#import "SPAppController.h" -#import "SPConnectionController.h" -#import "SPFavoritesOutlineView.h" -#import "SPWindow.h" - -#import "sequel-ace-Swift.h" - -@interface SPWindowController () - -- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc; -- (void)_selectedTableDocumentDeallocd:(NSNotification *)notification; - -@property (readwrite, strong) SPDatabaseDocument *selectedTableDocument; - -@end - -@implementation SPWindowController - -#pragma mark - -#pragma mark Initialisation - - -- (void)awakeFromNib { - [super awakeFromNib]; - - NSWindow *newWindow = [self window]; - - [self setupAppearance]; - [self setupConstraints]; - - [self _switchOutSelectedTableDocument:nil]; - - [newWindow setCollectionBehavior:[newWindow collectionBehavior] | NSWindowCollectionBehaviorFullScreenPrimary]; - - // Disable automatic cascading - this occurs before the size is set, so let the app - // controller apply cascading after frame autosaving. - [self setShouldCascadeWindows:NO]; - - // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. - NSMenu *mainMenu = [NSApp mainMenu]; - _closeWindowMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileClose]; - _closeTabMenuItem = [[[mainMenu itemWithTag:SPMainMenuFile] submenu] itemWithTag:SPMainMenuFileCloseTab]; - - // Because we are a document-based app we automatically adopt window restoration on 10.7+. - // However that causes a race condition with our own window setup code. - // Remove this when we actually support restoration. - if ([newWindow respondsToSelector:@selector(setRestorable:)]) { - [newWindow setRestorable:NO]; - } -} - -#pragma mark - -#pragma mark Database connection management - -- (SPDatabaseDocument *)addNewConnection -{ - // Create a new database connection view - SPDatabaseDocument *databaseDocument = [[SPDatabaseDocument alloc] initWithWindowController:self]; - self.selectedTableDocument = databaseDocument; - [self.window.contentView addSubview:[databaseDocument databaseView]]; - [[databaseDocument databaseView] setFrame:self.window.contentView.frame]; - - // Tell the new database connection view to set up the window and update titles - [databaseDocument didBecomeActiveTabInWindow]; - [databaseDocument updateWindowTitle:self]; - - return databaseDocument; -} - -/** - * Close the current tab, or if it's the last in the window, the window. - */ -- (IBAction)closeTab:(id)sender -{ - - //trying to close the window will itself call parentTabShouldClose for all tabs in windowShouldClose: - [[self window] performClose:self]; - [self.delegate windowControllerDidClose:self]; -} - -/** - * Menu item validation. - */ -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { - - // See if the front document blocks validation of this item - if (![self.selectedTableDocument validateMenuItem:menuItem]) return NO; - - return YES; -} - -/** - * Opens the current connection in a new tab, but only if it's already connected. - */ -- (void)openDatabaseInNewTab -{ - if ([self.selectedTableDocument database]) { - [self.selectedTableDocument openDatabaseInNewTab:self]; - } -} - -#pragma mark - -#pragma mark First responder forwarding to active tab - -/** - * Delegate unrecognised methods to the selected table document, thanks to the magic - * of NSInvocation (see forwardInvocation: docs for background). Must be paired - * with methodSignationForSelector:. - */ -- (void)forwardInvocation:(NSInvocation *)theInvocation -{ - SEL theSelector = [theInvocation selector]; - - if (![self.selectedTableDocument respondsToSelector:theSelector]) { - [self doesNotRecognizeSelector:theSelector]; - } - - [theInvocation invokeWithTarget:self.selectedTableDocument]; -} - -/** - * Return the correct method signatures for the selected table document if - * NSObject doesn't implement the requested methods. - */ -- (NSMethodSignature *)methodSignatureForSelector:(SEL)theSelector -{ - NSMethodSignature *defaultSignature = [super methodSignatureForSelector:theSelector]; - - return defaultSignature ? defaultSignature : [self.selectedTableDocument methodSignatureForSelector:theSelector]; -} - -/** - * Override the default repondsToSelector:, returning true if either NSObject - * or the selected table document supports the selector. - */ -- (BOOL)respondsToSelector:(SEL)theSelector -{ - return ([super respondsToSelector:theSelector] || [self.selectedTableDocument respondsToSelector:theSelector]); -} - -#pragma mark - -#pragma mark Private API - -- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc -{ - NSAssert([NSThread isMainThread], @"Switching the selectedTableDocument via a background thread is not supported!"); - - // shortcut if there is nothing to do - if (self.selectedTableDocument == newDoc) { - return; - } - - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - if (self.selectedTableDocument) { - [nc removeObserver:self name:SPDocumentWillCloseNotification object:self.selectedTableDocument]; - self.selectedTableDocument = nil; - } - if (newDoc) { - [nc addObserver:self selector:@selector(_selectedTableDocumentDeallocd:) name:SPDocumentWillCloseNotification object:newDoc]; - self.selectedTableDocument = newDoc; - } -} - -- (void)_selectedTableDocumentDeallocd:(NSNotification *)notification -{ - [self _switchOutSelectedTableDocument:nil]; -} - -#pragma mark - - -- (void)dealloc { - [self _switchOutSelectedTableDocument:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [NSObject cancelPreviousPerformRequestsWithTarget:self]; -} - -@end diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index 87be2bd21..71721e1a3 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -9,13 +9,33 @@ import Cocoa import SnapKit -extension SPWindowController { - @objc func setupAppearance() { - // Here should happen all UI / layout setups in the future once we remove .xib +@objc protocol SPWindowControllerDelegate: AnyObject { + func windowControllerDidClose(_ windowController: SPWindowController) +} + +@objc final class SPWindowController: NSWindowController { + + @objc weak var delegate: SPWindowControllerDelegate? + + @objc lazy var selectedTableDocument: SPDatabaseDocument = SPDatabaseDocument(windowController: self) + + override func awakeFromNib() { + super.awakeFromNib() + + if let window = window { + window.collectionBehavior = [window.collectionBehavior, .fullScreenPrimary] + } + + selectedTableDocument.didBecomeActiveTabInWindow() + selectedTableDocument.updateWindowTitle(self) + + setupAppearance() } - @objc func setupConstraints() { - // Here we will set constraints in the future once we remove .xib, for now, commented out as it crashes + func setupAppearance() { + // Here should happen all UI / layout setups in the future once we remove .xib + window?.contentView?.addSubview(selectedTableDocument.databaseView()) + selectedTableDocument.databaseView()?.frame = window?.contentView?.frame ?? NSRect(x: 0, y: 0, width: 800, height: 400) } } @@ -33,30 +53,7 @@ extension SPWindowController: NSWindowDelegate { appDelegate.setSessionURL(nil) appDelegate.setSpfSessionDocData(nil) } - delegate.windowControllerDidClose(self) + delegate?.windowControllerDidClose(self) return true } - - public func windowDidBecomeKey(_ notification: Notification) { - selectedTableDocument.tabDidBecomeKey() - - // Update close tab - closeTabMenuItem.isEnabled = true - closeTabMenuItem.keyEquivalent = "w" - closeTabMenuItem.keyEquivalentModifierMask = .command - - // Update the "Close" item to show "Close window" - closeWindowMenuItem.title = NSLocalizedString("Close Window", comment: "Close Window menu item") - closeWindowMenuItem.keyEquivalentModifierMask = [.command, .shift] - } - - public func windowDidResignKey(_ notification: Notification) { - // Update close tab - closeTabMenuItem.isEnabled = true - closeTabMenuItem.keyEquivalentModifierMask = [.command, .shift] - - // Update the "Close window" item to show only "Close" - closeWindowMenuItem.title = NSLocalizedString("Close", comment: "Close menu item") - closeWindowMenuItem.keyEquivalentModifierMask = .command - } } diff --git a/Source/Other/CategoryAdditions/SPTextViewAdditions.m b/Source/Other/CategoryAdditions/SPTextViewAdditions.m index c0b367fde..f5ad7fbb1 100644 --- a/Source/Other/CategoryAdditions/SPTextViewAdditions.m +++ b/Source/Other/CategoryAdditions/SPTextViewAdditions.m @@ -34,7 +34,6 @@ #import "SPAppController.h" #import "SPFieldEditorController.h" #import "SPTextView.h" -#import "SPWindowController.h" #import "SPDatabaseDocument.h" #import "SPBundleCommandRunner.h" #import "SPBundleManager.h" diff --git a/Source/Other/CategoryAdditions/SPWindowAdditions.m b/Source/Other/CategoryAdditions/SPWindowAdditions.m index e29490ee0..ff35910e4 100644 --- a/Source/Other/CategoryAdditions/SPWindowAdditions.m +++ b/Source/Other/CategoryAdditions/SPWindowAdditions.m @@ -30,7 +30,8 @@ #import "SPWindowAdditions.h" #import "SPDatabaseDocument.h" -#import "SPWindowController.h" + +#import "sequel-ace-Swift.h" @implementation NSWindow (SPWindowAdditions) diff --git a/Source/Sequel-Ace-Bridging-Header.h b/Source/Sequel-Ace-Bridging-Header.h index 3ae9eb460..219e58c20 100644 --- a/Source/Sequel-Ace-Bridging-Header.h +++ b/Source/Sequel-Ace-Bridging-Header.h @@ -28,7 +28,6 @@ // #import "SPAppController.h" -#import "SPWindowController.h" #import "SPDatabaseDocument.h" #import "SPConstants.h" diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index ef8437b3b..a48f020d9 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -29,7 +29,6 @@ // More info at #import "SPWindow.h" -#import "SPWindowController.h" #import "SPDatabaseDocument.h" #import "sequel-ace-Swift.h" diff --git a/Source/Views/TableViews/SPTableView.m b/Source/Views/TableViews/SPTableView.m index 6ec38ed0b..d8bb83b97 100644 --- a/Source/Views/TableViews/SPTableView.m +++ b/Source/Views/TableViews/SPTableView.m @@ -31,9 +31,10 @@ #import "SPTableView.h" #import "SPQueryFavoriteManager.h" #import "SPDatabaseDocument.h" -#import "SPWindowController.h" #import "SPFieldMapperController.h" +#import "sequel-ace-Swift.h" + @protocol SPTableViewDelegate @optional - (BOOL)cancelRowEditing; diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index cb1c0c084..7c1f66983 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -329,7 +329,6 @@ 589235321020C1230011DE00 /* SPHistoryController.m in Sources */ = {isa = PBXBuildFile; fileRef = 589235301020C1230011DE00 /* SPHistoryController.m */; }; 589582151154F8F400EDCC28 /* SPMainThreadTrampoline.m in Sources */ = {isa = PBXBuildFile; fileRef = 589582141154F8F400EDCC28 /* SPMainThreadTrampoline.m */; }; 58A137CD123ED5E6000B1B75 /* titlebarlock.png in Resources */ = {isa = PBXBuildFile; fileRef = 58A137CC123ED5E6000B1B75 /* titlebarlock.png */; }; - 58A8A79111A036C000B95749 /* SPWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 58A8A79011A036C000B95749 /* SPWindowController.m */; }; 58B9097B11C3A4A2000826E5 /* xibLocalizationPostprocessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 58B9095B11C3A3EC000826E5 /* xibLocalizationPostprocessor.m */; }; 58C56EF50F438E120035701E /* SPDataCellFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C56EF40F438E120035701E /* SPDataCellFormatter.m */; }; 58CDB3300FCE138D00F8ACA3 /* SPSSHTunnel.m in Sources */ = {isa = PBXBuildFile; fileRef = 58CDB32F0FCE138D00F8ACA3 /* SPSSHTunnel.m */; }; @@ -977,8 +976,6 @@ 589582131154F8F400EDCC28 /* SPMainThreadTrampoline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPMainThreadTrampoline.h; sourceTree = ""; }; 589582141154F8F400EDCC28 /* SPMainThreadTrampoline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPMainThreadTrampoline.m; sourceTree = ""; }; 58A137CC123ED5E6000B1B75 /* titlebarlock.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = titlebarlock.png; sourceTree = ""; }; - 58A8A78F11A036C000B95749 /* SPWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPWindowController.h; sourceTree = ""; }; - 58A8A79011A036C000B95749 /* SPWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPWindowController.m; sourceTree = ""; }; 58B9077D11BD9B64000826E5 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; 58B9088711BDB7AA000826E5 /* PSMTabBar-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PSMTabBar-Info.plist"; path = "Plists/PSMTabBar-Info.plist"; sourceTree = ""; }; 58B9095B11C3A3EC000826E5 /* xibLocalizationPostprocessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = xibLocalizationPostprocessor.m; sourceTree = ""; }; @@ -1552,8 +1549,6 @@ 17D3583C1533766800A654D7 /* Window */ = { isa = PBXGroup; children = ( - 58A8A78F11A036C000B95749 /* SPWindowController.h */, - 58A8A79011A036C000B95749 /* SPWindowController.m */, 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */, ); path = Window; @@ -2942,7 +2937,6 @@ 1198F5B31174EDD500670590 /* SPDatabaseCopy.m in Sources */, 1141A389117BBFF200126A28 /* SPTableCopy.m in Sources */, 11B55BFE1189E3B2009EF465 /* SPDatabaseAction.m in Sources */, - 58A8A79111A036C000B95749 /* SPWindowController.m in Sources */, 1AF5A261250AC401009885DF /* SPBracketHighlighter.m in Sources */, 5806B76411A991EC00813A88 /* SPDocumentController.m in Sources */, 173C837211AAD26E00B8B084 /* SPExportUtilities.m in Sources */, From cddfb9ce4aa016b89f1ea367d6970397513f1134 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sun, 7 Mar 2021 22:37:23 +0100 Subject: [PATCH 05/41] Move setup to setupAppearance --- Source/Controllers/Window/SPWindowController.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index 71721e1a3..b7698c259 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -26,14 +26,13 @@ import SnapKit window.collectionBehavior = [window.collectionBehavior, .fullScreenPrimary] } - selectedTableDocument.didBecomeActiveTabInWindow() - selectedTableDocument.updateWindowTitle(self) - setupAppearance() } func setupAppearance() { - // Here should happen all UI / layout setups in the future once we remove .xib + selectedTableDocument.didBecomeActiveTabInWindow() + selectedTableDocument.updateWindowTitle(self) + window?.contentView?.addSubview(selectedTableDocument.databaseView()) selectedTableDocument.databaseView()?.frame = window?.contentView?.frame ?? NSRect(x: 0, y: 0, width: 800, height: 400) } From 1414cdaeb8442f5fdc3b626e433fd93baa8a5362 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Mon, 8 Mar 2021 00:42:48 +0100 Subject: [PATCH 06/41] Add tab manager and allow tabbing --- Interfaces/MainWindow.xib | 2 +- Source/Controllers/SPAppController.h | 4 +- Source/Controllers/SPAppController.m | 181 +++++------------- .../Window/NotificationToken.swift | 58 ++++++ .../Window/SPWindowController.swift | 24 ++- Source/Controllers/Window/TabManager.swift | 157 +++++++++++++++ sequel-ace.xcodeproj/project.pbxproj | 8 + 7 files changed, 295 insertions(+), 139 deletions(-) create mode 100644 Source/Controllers/Window/NotificationToken.swift create mode 100644 Source/Controllers/Window/TabManager.swift diff --git a/Interfaces/MainWindow.xib b/Interfaces/MainWindow.xib index 29ad4f328..ebc2907a6 100644 --- a/Interfaces/MainWindow.xib +++ b/Interfaces/MainWindow.xib @@ -13,7 +13,7 @@ - + diff --git a/Source/Controllers/SPAppController.h b/Source/Controllers/SPAppController.h index c626ce3fb..38c25c1d2 100755 --- a/Source/Controllers/SPAppController.h +++ b/Source/Controllers/SPAppController.h @@ -39,7 +39,9 @@ @class SPWindowController; @class HyperlinkTextField; -@interface SPAppController : NSObject +@protocol SPWindowControllerDelegate; + +@interface SPAppController : NSObject { SPAboutController *aboutController; SPPreferenceController *prefsController; diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 18a0e4828..fee03d88e 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -61,7 +61,7 @@ static const double SPDelayBeforeCheckingForNewReleases = 10; -@interface SPAppController () +@interface SPAppController () @property (strong) IBOutlet NSMenu *mainMenu; - (void)_copyDefaultThemes; @@ -79,6 +79,8 @@ - (void)checkForNewVersionFromMenu; @property (readwrite, strong) SPBundleManager *sharedSPBundleManager; @property (nonatomic, strong, readwrite) NSMutableArray *windowControllers; +@property (nonatomic, strong) TabManager *tabManager; + @end @implementation SPAppController @@ -106,6 +108,7 @@ - (instancetype)init runningActivitiesArray = [[NSMutableArray alloc] init]; sshProcessIDs = [[NSMutableArray alloc] init]; fileManager = [NSFileManager defaultManager]; + _tabManager = [[TabManager alloc] initWithAppController:self]; //Create runtime directiories [fileManager createDirectoryAtPath:[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"] withIntermediateDirectories:true attributes:nil error:nil]; @@ -285,19 +288,19 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(externalApplicationWantsToOpenADatabaseConnection:) name:@"ExternalApplicationWantsToOpenADatabaseConnection" object:nil]; [sharedSPBundleManager reloadBundles:self]; - [self _copyDefaultThemes]; + [self _copyDefaultThemes];; // If no documents are open, open one if (![self frontDocument]) { - SPDatabaseDocument *newConnection = [self createNewDatabaseDocument]; + SPWindowController *newWindowController = [self.tabManager replaceTabServiceWithInitialWindow]; if (spfDict) { - [newConnection setState:spfDict]; + [newWindowController.selectedTableDocument setState:spfDict]; } // Set autoconnection if appropriate if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault] && secureBookmarkManager.staleBookmarks.count == 0) { - [newConnection connect]; + [newWindowController.selectedTableDocument connect]; } } } @@ -347,15 +350,14 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } } -- (void)externalApplicationWantsToOpenADatabaseConnection:(NSNotification *)notification -{ +- (void)externalApplicationWantsToOpenADatabaseConnection:(NSNotification *)notification { NSDictionary *userInfo = [notification userInfo]; NSString *MAMP_SPFVersion = [userInfo objectForKey:@"dataVersion"]; if ([MAMP_SPFVersion isEqualToString:@"1"]) { NSDictionary *spfStructure = [userInfo objectForKey:@"spfData"]; if (spfStructure) { - SPDatabaseDocument *frontDoc = [self createNewDatabaseDocument]; - [frontDoc setState:spfStructure]; + SPWindowController *windowController = [self.tabManager newWindowForWindow]; + [windowController.selectedTableDocument setState:spfStructure]; } } } @@ -373,7 +375,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem } if ([menuItem action] == @selector(newTab:)) { - return ([[self.activeWindowController window] attachedSheet] == nil); + return ([[[self.tabManager activeWindowController] window] attachedSheet] == nil); } if ([menuItem action] == @selector(duplicateTab:)) @@ -436,9 +438,9 @@ - (IBAction)openConnectionSheet:(id)sender [panel setAllowedFileTypes:@[SPFileExtensionDefault, SPFileExtensionSQL, SPBundleFileExtension]]; // Check if at least one document exists, if so show a sheet - if (self.activeWindowController) { + if ([self.tabManager activeWindowController]) { - [panel beginSheetModalForWindow:[self.activeWindowController window] completionHandler:^(NSInteger returnCode) { + [panel beginSheetModalForWindow:[[self.tabManager activeWindowController] window] completionHandler:^(NSInteger returnCode) { if (returnCode) { [panel orderOut:self]; @@ -504,12 +506,9 @@ - (void)application:(NSApplication *)app openFiles:(NSArray *)filenames } } -- (void)openConnectionFileAtPath:(NSString *)filePath -{ - SPDatabaseDocument *frontDocument = [self createNewDatabaseDocument]; - - [frontDocument setStateFromConnectionFile:filePath]; - +- (void)openConnectionFileAtPath:(NSString *)filePath { + SPWindowController *windowController = [self.tabManager newWindowForWindow]; + [windowController.selectedTableDocument setStateFromConnectionFile:filePath]; [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:filePath]]; } @@ -592,8 +591,8 @@ - (void)openSQLFileAtPath:(NSString *)filePath } // Check if at least one document exists. If not, open one. - if (!frontDocument) { - frontDocument = [self createNewDatabaseDocument]; + if (![self.tabManager activeWindowController]) { + frontDocument = [self.tabManager newWindowForWindow].selectedTableDocument; [frontDocument initQueryEditorWithString:sqlString]; } else { @@ -768,42 +767,43 @@ - (void)handleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEvent } } -- (void)handleMySQLConnectWithURL:(NSURL *)url -{ +- (void)handleMySQLConnectWithURL:(NSURL *)url { if(![[url scheme] isEqualToString:@"mysql"]) { SPLog(@"unsupported url scheme: %@",url); return; } - // make connection window - SPDatabaseDocument *doc = [self createNewDatabaseDocument]; - NSMutableDictionary *details = [NSMutableDictionary dictionary]; NSValue *connect = @NO; [details setObject:@"SPTCPIPConnection" forKey:@"type"]; - if([url port]) + if ([url port]) { [details setObject:[url port] forKey:@"port"]; + } - if([url user]) + if ([url user]) { [details setObject:[url user] forKey:@"user"]; + } - if([url password]) { + if ([url password]) { [details setObject:[url password] forKey:@"password"]; connect = @YES; } - if([[url host] length]) + if ([[url host] length]) { [details setObject:[url host] forKey:@"host"]; - else + } else { [details setObject:@"127.0.0.1" forKey:@"host"]; + } NSArray *pc = [url pathComponents]; - if([pc count] > 1) // first object is "/" + if ([pc count] > 1) { // first object is "/" [details setObject:[pc objectAtIndex:1] forKey:@"database"]; + } - [doc setState:@{@"connection":details,@"auto_connect": connect} fromFile:NO]; + SPWindowController *windowController = [self.tabManager newWindowForWindow]; + [windowController.selectedTableDocument setState:@{@"connection":details,@"auto_connect": connect} fromFile:NO]; } - (void)handleEventWithURL:(NSURL*)url @@ -1230,7 +1230,7 @@ - (SPPreferenceController *)preferenceController * Retrieve the frontmost document; returns nil if not found. */ - (SPDatabaseDocument *)frontDocument { - return [self.activeWindowController selectedTableDocument]; + return [[self.tabManager activeWindowController] selectedTableDocument]; } /** @@ -1337,8 +1337,8 @@ - (IBAction)viewKeyboardShortcuts:(id)sender - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { // Only create a new document (without auto-connect) when there are already no documents open. - if (![self frontDocument]) { - [self newWindowController]; + if (![self.tabManager activeWindowController]) { + [self.tabManager newWindowForWindow]; return NO; } // Return YES to the automatic opening @@ -1514,117 +1514,27 @@ - (id)handlePrintScriptCommand:(NSScriptCommand *)command #pragma mark - SPWindowManagement -- (IBAction)newWindow:(id)sender -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [self newWindowController]; - }); +- (IBAction)newWindowForTab:(id)sender { + [self.tabManager newWindowForTab]; } -/** - * Create a new window, containing a single tab. - */ -- (SPWindowController *)newWindowController { - 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"]; - newWindowController.delegate = self; - NSWindow *newWindow = [newWindowController window]; - - // 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, and perform frontmost tasks again once the window has drawn - [newWindowController showWindow:self]; - [[newWindowController selectedTableDocument] didBecomeActiveTabInWindow]; - - [self.windowControllers addObject:newWindowController]; - - return newWindowController; +- (IBAction)newWindow:(id)sender { + [self.tabManager newWindowForWindow]; } /** * Create a new tab in the frontmost window. */ - (IBAction)newTab:(id)sender { - - // No root window means - if (!self.activeWindowController) { - [self newWindowController]; - } else { -// if ([[self.activeWindowController window] isMiniaturized]) { -// [[self.activeWindowController window] deminiaturize:self]; -// } -// [self.activeWindowController addNewConnection]; - } -} - -- (SPDatabaseDocument *)createNewDatabaseDocument { - - SPDatabaseDocument *databaseDocument; - - // If no window was found or the front most window has no tabs, create a new one - if (!self.activeWindowController || [[[self activeWindowController] valueForKeyPath:@"tabView"] numberOfTabViewItems] == 1) { - [self newWindowController]; - databaseDocument = [self.activeWindowController selectedTableDocument]; - } - // Open the spf file in a new tab if the tab bar is visible -// else { -// if ([[self.activeWindowController window] isMiniaturized]) { -// [[self.activeWindowController window] deminiaturize:self]; -// } -// databaseDocument = [self.activeWindowController addNewConnection]; -// } - return databaseDocument; -} - -- (SPWindowController *)activeWindowController { - if (self.windowControllers.count == 0) { - return nil; - } - for (SPWindowController *windowController in self.windowControllers) { - if ([windowController.window isKeyWindow]) { - return windowController; - } - } - SPWindowController *windowController = [self.windowControllers firstObject]; - [windowController.window makeKeyAndOrderFront:nil]; - return windowController; + [self.tabManager newWindowForTab]; } /** * Duplicate the current connection tab */ -- (IBAction)duplicateTab:(id)sender -{ - SPDatabaseDocument *theFrontDocument = [self frontDocument]; +- (IBAction)duplicateTab:(id)sender { - if (!theFrontDocument) { - return [self newTab:sender]; - } - - // Add a new tab to the window - if ([[self.activeWindowController window] isMiniaturized]) { - [[self.activeWindowController window] deminiaturize:self]; - } + SPWindowController *newWindowController = [self.tabManager newWindowForTab]; // Get the state of the previously-frontmost document NSDictionary *allStateDetails = @{ @@ -1635,14 +1545,13 @@ - (IBAction)duplicateTab:(id)sender @"password" : @YES }; - NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[theFrontDocument stateIncludingDetails:allStateDetails]]; + NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[newWindowController.selectedTableDocument stateIncludingDetails:allStateDetails]]; // Ensure it's set to autoconnect [frontState setObject:@YES forKey:@"auto_connect"]; -// SPDatabaseDocument *newConnection = [self.activeWindowController addNewConnection]; -// // Set the connection on the new tab -// [newConnection setState:frontState]; + // Set the connection on the new tab + [newWindowController.selectedTableDocument setState:frontState]; } #pragma mark - NSWindowDelegate diff --git a/Source/Controllers/Window/NotificationToken.swift b/Source/Controllers/Window/NotificationToken.swift new file mode 100644 index 000000000..4088f76b9 --- /dev/null +++ b/Source/Controllers/Window/NotificationToken.swift @@ -0,0 +1,58 @@ +// +// NotificationToken.swift +// Sequel Ace +// +// Created by Jakub Kašpar on 07.03.2021. +// Copyright © 2021 Sequel-Ace. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// More info at + +import Foundation + +/// Wraps the observer token received from +/// NotificationCenter.addObserver(forName:object:queue:using:) +/// and unregisters it in deinit. +final class NotificationToken: NSObject { + let notificationCenter: NotificationCenter + let token: Any + + init(notificationCenter: NotificationCenter = .default, token: Any) { + self.notificationCenter = notificationCenter + self.token = token + } + + deinit { + notificationCenter.removeObserver(token) + } +} + +extension NotificationCenter { + /// Convenience wrapper for addObserver(forName:object:queue:using:) + /// that returns our custom NotificationToken. + func observe(name: NSNotification.Name?, object obj: Any?, queue: OperationQueue? = nil, using block: @escaping (Notification) -> ()) -> NotificationToken + { + let token = addObserver(forName: name, object: obj, queue: queue, using: block) + return NotificationToken(notificationCenter: self, token: token) + } +} diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index b7698c259..f554c6555 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -5,6 +5,28 @@ // Created by Jakub Kašpar on 24.01.2021. // Copyright © 2021 Sequel-Ace. All rights reserved. // +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// More info at import Cocoa import SnapKit @@ -29,7 +51,7 @@ import SnapKit setupAppearance() } - func setupAppearance() { + private func setupAppearance() { selectedTableDocument.didBecomeActiveTabInWindow() selectedTableDocument.updateWindowTitle(self) diff --git a/Source/Controllers/Window/TabManager.swift b/Source/Controllers/Window/TabManager.swift new file mode 100644 index 000000000..39cbaec13 --- /dev/null +++ b/Source/Controllers/Window/TabManager.swift @@ -0,0 +1,157 @@ +// +// TabManager.swift +// Sequel Ace +// +// Created by Jakub Kašpar on 07.03.2021. +// Copyright © 2021 Sequel-Ace. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// More info at + +import AppKit + +@objc final class TabManager: NSObject { + + // MARK: - Custom struct + + private struct ManagedWindow { + /// Keep the controller around to store a strong reference to it + let windowController: SPWindowController + + /// Keep the window around to identify instances of this type + let window: NSWindow + + /// React to window closing, auto-unsubscribing on dealloc + let closingSubscription: NotificationToken + } + + // MARK: - Private properties + + private var managedWindows: [ManagedWindow] = [] + + /// Returns the main window of the managed window stack. + /// Falls back the first element if no window is main. Note that this would + /// likely be an internal inconsistency we gracefully handle here. + private var mainWindow: NSWindow? { + let mainManagedWindow = managedWindows.first { $0.window.isMainWindow } + + // In case we run into the inconsistency, let it crash in debug mode so we + // can fix our window management setup to prevent this from happening. + assert(mainManagedWindow != nil || managedWindows.isEmpty) + + return (mainManagedWindow ?? managedWindows.first).map { $0.window } + } + + // MARK: - Public properties + + @objc var activeWindowController: SPWindowController? { + return managedWindows.first { $0.window.isMainWindow }?.windowController + } + + weak var appController: SPAppController? + + // MARK: - Lifecycle + + @objc init(appController: SPAppController) { + self.appController = appController + + super.init() + } + + // MARK: - Public API + + @discardableResult + @objc func newWindowForTab() -> SPWindowController { + if let existingWindow = mainWindow { + let windowController = createNewWindowController() + createTab(newWindowController: windowController, inWindow: existingWindow, ordered: .above) + return windowController + } else { + return replaceTabServiceWithInitialWindow() + } + } + + @discardableResult + @objc func newWindowForWindow() -> SPWindowController { + let windowController = createNewWindowController() + createWindow(newWindowController: windowController, inWindow: NSWindow(), ordered: .above) + return windowController + } + + @discardableResult + @objc func replaceTabServiceWithInitialWindow() -> SPWindowController { + let windowController = createNewWindowController() + addManagedWindow(windowController: windowController) + return windowController + } +} + +// MARK: - Private API + +private extension TabManager { + func createNewWindowController() -> SPWindowController { + let windowController = SPWindowController(windowNibName: "MainWindow") + windowController.delegate = appController + windowController.window?.delegate = appController + windowController.showWindow(self) + windowController.selectedTableDocument.didBecomeActiveTabInWindow() + return windowController + } + + func createTab(newWindowController: SPWindowController, inWindow window: NSWindow, ordered orderingMode: NSWindow.OrderingMode) { + + guard let newWindow = addManagedWindow(windowController: newWindowController)?.window else { preconditionFailure() } + + window.addTabbedWindow(newWindow, ordered: orderingMode) + newWindow.makeKeyAndOrderFront(nil) + } + + func createWindow(newWindowController: SPWindowController, inWindow window: NSWindow, ordered orderingMode: NSWindow.OrderingMode) { + + guard let newWindow = addManagedWindow(windowController: newWindowController)?.window else { preconditionFailure() } + + window.addChildWindow(newWindow, ordered: orderingMode) + newWindow.makeKeyAndOrderFront(nil) + } + + @discardableResult + private func addManagedWindow(windowController: SPWindowController) -> ManagedWindow? { + guard let window = windowController.window else { + return nil + } + + let subscription = NotificationCenter.default.observe(name: NSWindow.willCloseNotification, object: window) { [unowned self] notification in + guard let window = notification.object as? NSWindow else { + return + } + self.removeManagedWindow(forWindow: window) + } + let management = ManagedWindow(windowController: windowController, window: window, closingSubscription: subscription) + managedWindows.append(management) + return management + } + + func removeManagedWindow(forWindow window: NSWindow) { + managedWindows.removeAll(where: { $0.window === window }) + } +} diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index 7c1f66983..db053f03b 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -227,6 +227,8 @@ 50EA92681AB23EFC008D3C4F /* SPTableCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1141A388117BBFF200126A28 /* SPTableCopy.m */; }; 50EA926A1AB246B8008D3C4F /* SPDatabaseActionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50EA92691AB246B8008D3C4F /* SPDatabaseActionTest.m */; }; 50F530521ABCF66B002F2C1A /* resetTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 50F530511ABCF66B002F2C1A /* resetTemplate.pdf */; }; + 5132930C25F586A900D803AD /* NotificationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132930925F586A900D803AD /* NotificationToken.swift */; }; + 5132930D25F586A900D803AD /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132930A25F586A900D803AD /* TabManager.swift */; }; 513515D2259354BB001E4533 /* NSImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513515D1259354BB001E4533 /* NSImageExtensions.swift */; }; 515D303F25BD7DE60021CF1E /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = 515D303E25BD7DE60021CF1E /* AppCenterCrashes */; }; 515D304125BD7DE60021CF1E /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 515D304025BD7DE60021CF1E /* AppCenterAnalytics */; }; @@ -854,6 +856,8 @@ 50EA92691AB246B8008D3C4F /* SPDatabaseActionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDatabaseActionTest.m; sourceTree = ""; }; 50F530511ABCF66B002F2C1A /* resetTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = resetTemplate.pdf; sourceTree = ""; }; 511B309F25ABBC6500D010E3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 5132930925F586A900D803AD /* NotificationToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationToken.swift; sourceTree = ""; }; + 5132930A25F586A900D803AD /* TabManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = ""; }; 513515D1259354BB001E4533 /* NSImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSImageExtensions.swift; sourceTree = ""; }; 5174122E2573E10C00EB6935 /* SPPrintUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPPrintUtility.h; sourceTree = ""; }; 5174122F2573E10C00EB6935 /* SPPrintUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPPrintUtility.m; sourceTree = ""; }; @@ -1549,6 +1553,8 @@ 17D3583C1533766800A654D7 /* Window */ = { isa = PBXGroup; children = ( + 5132930925F586A900D803AD /* NotificationToken.swift */, + 5132930A25F586A900D803AD /* TabManager.swift */, 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */, ); path = Window; @@ -2915,6 +2921,7 @@ 1ABC770125E3895300E8EE01 /* DispatchQueueExtension.swift in Sources */, 5822D3091061833C00CE2157 /* SPCSVParser.m in Sources */, 1AD785E725B749760007E153 /* OSLog.swift in Sources */, + 5132930C25F586A900D803AD /* NotificationToken.swift in Sources */, BC675A141072039C00C5ACD4 /* SPContentFilterManager.m in Sources */, 17292443107AC41000B21980 /* SPXMLExporter.m in Sources */, 582A01E9107C0C170027D42B /* SPNotLoaded.m in Sources */, @@ -3012,6 +3019,7 @@ 50E217B618174280009D3580 /* SPFavoriteColorSupport.m in Sources */, 1A6377D4259B414400B1E96D /* SecureBookmark.swift in Sources */, 1A564F74237E2E4958CA593A /* SPPillAttachmentCell.m in Sources */, + 5132930D25F586A900D803AD /* TabManager.swift in Sources */, 9BE76F2886901784E4FD2321 /* SPFilterTableController.m in Sources */, 9BE765EBBDFD2F121C13D274 /* SPFillView.m in Sources */, 9BE76F2B943AFDBA6EDC52BE /* SPHelpViewerController.m in Sources */, From 65f20a53eb47bed975d46119e6cb0b2644e95121 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Mon, 8 Mar 2021 00:43:18 +0100 Subject: [PATCH 07/41] Sort files in folders --- sequel-ace.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index db053f03b..4d96a5511 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -1554,8 +1554,8 @@ isa = PBXGroup; children = ( 5132930925F586A900D803AD /* NotificationToken.swift */, - 5132930A25F586A900D803AD /* TabManager.swift */, 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */, + 5132930A25F586A900D803AD /* TabManager.swift */, ); path = Window; sourceTree = ""; @@ -1775,17 +1775,17 @@ 17E641470EF01EB8001BC333 /* Controllers */ = { isa = PBXGroup; children = ( - 17E6414A0EF01EF6001BC333 /* SPAppController.h */, - 17E6414B0EF01EF6001BC333 /* SPAppController.m */, - 17D3583C1533766800A654D7 /* Window */, 173567BA12AC1306000DCCEF /* Bundle Support */, - 173E70A6107FF61D008733C9 /* Main View Controllers */, - 173E70D2107FF687008733C9 /* Subview Controllers */, 173E70D4107FF6E7008733C9 /* Data Controllers */, - 17D38EFB12777B2300672B13 /* Data Import */, 17F5B1491048C4C000FC794F /* Data Export */, - 17D390A6127B54F300672B13 /* Preferences */, + 17D38EFB12777B2300672B13 /* Data Import */, + 173E70A6107FF61D008733C9 /* Main View Controllers */, 173E70D5107FF7AF008733C9 /* Other */, + 17D390A6127B54F300672B13 /* Preferences */, + 17E6414A0EF01EF6001BC333 /* SPAppController.h */, + 17E6414B0EF01EF6001BC333 /* SPAppController.m */, + 173E70D2107FF687008733C9 /* Subview Controllers */, + 17D3583C1533766800A654D7 /* Window */, ); path = Controllers; sourceTree = ""; From 9b638e265643a57434d4c06b5c1897f1389ef906 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Mon, 8 Mar 2021 00:52:30 +0100 Subject: [PATCH 08/41] Add TODOs --- Source/Controllers/MainViewControllers/SPDatabaseDocument.m | 1 + Source/Controllers/SubviewControllers/SPTablesList.m | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 62ba0ce56..dccf060e6 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3215,6 +3215,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB - (IBAction)openDatabaseInNewTab:(id)sender { // Add a new tab to the window + // TODO // [self.parentWindowController addNewConnection]; // Get the current state diff --git a/Source/Controllers/SubviewControllers/SPTablesList.m b/Source/Controllers/SubviewControllers/SPTablesList.m index a4591e846..c234c816c 100644 --- a/Source/Controllers/SubviewControllers/SPTablesList.m +++ b/Source/Controllers/SubviewControllers/SPTablesList.m @@ -716,6 +716,7 @@ - (IBAction)truncateTable:(id)sender { - (IBAction)openTableInNewTab:(id)sender { // Add a new tab to the window + // TODO // [[tableDocumentInstance parentWindowController] addNewConnection]; // // [self _duplicateConnectionToFrontTab]; From c39ae28acde3f4f55cc65b7723fb2b099c29ac2c Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Tue, 9 Mar 2021 23:32:03 +0100 Subject: [PATCH 09/41] Add new notification to call app controller to duplicate tab --- .../MainViewControllers/SPDatabaseDocument.m | 9 ++----- Source/Controllers/SPAppController.h | 4 +-- Source/Controllers/SPAppController.m | 25 ++++++++++--------- Source/Controllers/SPAppController.swift | 15 +++++++++++ Source/Other/Data/SPConstants.h | 1 + Source/Other/Data/SPConstants.m | 1 + sequel-ace.xcodeproj/project.pbxproj | 4 +++ 7 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 Source/Controllers/SPAppController.swift diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index dccf060e6..59049f75a 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3212,11 +3212,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB /** * Open the currently selected database in a new tab, clearing any table selection. */ -- (IBAction)openDatabaseInNewTab:(id)sender -{ - // Add a new tab to the window - // TODO -// [self.parentWindowController addNewConnection]; +- (IBAction)openDatabaseInNewTab:(id)sender { // Get the current state NSDictionary *allStateDetails = @{ @@ -3234,8 +3230,7 @@ - (IBAction)openDatabaseInNewTab:(id)sender [sessionDict removeObjectForKey:@"table"]; [currentState setObject:sessionDict forKey:@"session"]; - // Set the connection on the new tab - [[SPAppDelegate frontDocument] setState:currentState]; + [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentDuplicateTabNotification object:nil userInfo:currentState]; } /** diff --git a/Source/Controllers/SPAppController.h b/Source/Controllers/SPAppController.h index 38c25c1d2..c626ce3fb 100755 --- a/Source/Controllers/SPAppController.h +++ b/Source/Controllers/SPAppController.h @@ -39,9 +39,7 @@ @class SPWindowController; @class HyperlinkTextField; -@protocol SPWindowControllerDelegate; - -@interface SPAppController : NSObject +@interface SPAppController : NSObject { SPAboutController *aboutController; SPPreferenceController *prefsController; diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index fee03d88e..f06cbb936 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -122,7 +122,6 @@ - (instancetype)init //Register an observer to switch Appearance at runtime [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(defaultsChanged:) name:NSUserDefaultsDidChangeNotification object:nil]; } - [NSApp setDelegate:self]; } return self; @@ -287,6 +286,8 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(externalApplicationWantsToOpenADatabaseConnection:) name:@"ExternalApplicationWantsToOpenADatabaseConnection" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(duplicateConnectionToTab:) name:SPDocumentDuplicateTabNotification object:nil]; + [sharedSPBundleManager reloadBundles:self]; [self _copyDefaultThemes];; @@ -362,6 +363,15 @@ - (void)externalApplicationWantsToOpenADatabaseConnection:(NSNotification *)noti } } +- (void)duplicateConnectionToTab:(NSNotification *)notification { + + NSDictionary *userInfo = [notification userInfo]; + if (userInfo) { + SPWindowController *newWindowController = [self.tabManager newWindowForTab]; + [newWindowController.selectedTableDocument setState:userInfo]; + } +} + /** * Menu item validation. */ @@ -1534,8 +1544,6 @@ - (IBAction)newTab:(id)sender { */ - (IBAction)duplicateTab:(id)sender { - SPWindowController *newWindowController = [self.tabManager newWindowForTab]; - // Get the state of the previously-frontmost document NSDictionary *allStateDetails = @{ @"connection" : @YES, @@ -1545,13 +1553,12 @@ - (IBAction)duplicateTab:(id)sender { @"password" : @YES }; - NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[newWindowController.selectedTableDocument stateIncludingDetails:allStateDetails]]; + NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[self.tabManager.activeWindowController.selectedTableDocument stateIncludingDetails:allStateDetails]]; // Ensure it's set to autoconnect [frontState setObject:@YES forKey:@"auto_connect"]; - // Set the connection on the new tab - [newWindowController.selectedTableDocument setState:frontState]; + [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentDuplicateTabNotification object:nil userInfo:frontState]; } #pragma mark - NSWindowDelegate @@ -1694,10 +1701,4 @@ - (void)rebuildMenus{ } } -#pragma mark - SPWindowControllerDelegate - -- (void)windowControllerDidClose:(SPWindowController *)windowController { - [self.windowControllers removeObject:windowController]; -} - @end diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift new file mode 100644 index 000000000..06d7dc9d6 --- /dev/null +++ b/Source/Controllers/SPAppController.swift @@ -0,0 +1,15 @@ +// +// SPAppController.swift +// Sequel Ace +// +// Created by Jakub Kašpar on 09.03.2021. +// Copyright © 2021 Sequel-Ace. All rights reserved. +// + +import AppKit + +extension SPAppController: SPWindowControllerDelegate { + func windowControllerDidClose(_ windowController: SPWindowController) { + windowControllers.remove(windowController) + } +} diff --git a/Source/Other/Data/SPConstants.h b/Source/Other/Data/SPConstants.h index 82837d2a3..4c45f69f4 100755 --- a/Source/Other/Data/SPConstants.h +++ b/Source/Other/Data/SPConstants.h @@ -444,6 +444,7 @@ extern NSString *SPShowUpdateAvailable; extern NSString *SPDocumentTaskEndNotification; extern NSString *SPDocumentTaskStartNotification; extern NSString *SPDocumentWillCloseNotification; +extern NSString *SPDocumentDuplicateTabNotification; extern NSString *SPActivitiesUpdateNotification; extern NSString *SPWindowToolbarDidToggleNotification; extern NSString *SPFieldEditorSheetFont; diff --git a/Source/Other/Data/SPConstants.m b/Source/Other/Data/SPConstants.m index ead9666c2..b2d63613b 100755 --- a/Source/Other/Data/SPConstants.m +++ b/Source/Other/Data/SPConstants.m @@ -249,6 +249,7 @@ - (SPTableViewType)tableViewTypeEnumFromString{ NSString *SPBookmarksChangedNotification = @"BookmarksChangedNotification"; NSString *SPDocumentTaskStartNotification = @"DocumentTaskStarted"; NSString *SPDocumentWillCloseNotification = @"DocumentWillClose"; +NSString *SPDocumentDuplicateTabNotification = @"DocumentDuplicateTab"; NSString *SPActivitiesUpdateNotification = @"ActivitiesUpdateNotification"; NSString *SPWindowToolbarDidToggleNotification = @"WindowToolbarWasToggledNotification"; NSString *SPFieldEditorSheetFont = @"FieldEditorSheetFont"; diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index 4d96a5511..d61ad51bc 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -239,6 +239,7 @@ 519350302567D2FB001272B5 /* CollectionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5193502E2567D2FB001272B5 /* CollectionExtension.swift */; }; 51A709392565B99F001F1D2F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51A709382565B99F001F1D2F /* Images.xcassets */; }; 51BA34A625BD9F30007CA20B /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51BA34A525BD9F30007CA20B /* OCMock.framework */; }; + 51BB391C25F82B060048CA69 /* SPAppController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB391B25F82B060048CA69 /* SPAppController.swift */; }; 51BC14F825BE135500F1CDC9 /* SPWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */; }; 51BC150125BE138700F1CDC9 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 51BC150025BE138700F1CDC9 /* SnapKit */; }; 51BC150625BE13C400F1CDC9 /* NSViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC150525BE13C400F1CDC9 /* NSViewExtension.swift */; }; @@ -869,6 +870,7 @@ 5193502E2567D2FB001272B5 /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = ""; }; 51A709382565B99F001F1D2F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 51BA34A525BD9F30007CA20B /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = Frameworks/OCMock.framework; sourceTree = ""; }; + 51BB391B25F82B060048CA69 /* SPAppController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAppController.swift; sourceTree = ""; }; 51BB3DFC25AEF020005AAE44 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; 51BB3E0425AEF0D7005AAE44 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; 51BC14F725BE135500F1CDC9 /* SPWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPWindowController.swift; sourceTree = ""; }; @@ -1786,6 +1788,7 @@ 17E6414B0EF01EF6001BC333 /* SPAppController.m */, 173E70D2107FF687008733C9 /* Subview Controllers */, 17D3583C1533766800A654D7 /* Window */, + 51BB391B25F82B060048CA69 /* SPAppController.swift */, ); path = Controllers; sourceTree = ""; @@ -2893,6 +2896,7 @@ BC2C16D40FEBEDF10003993B /* SPDataAdditions.m in Sources */, 5822C9B51000DB2400DCC3D6 /* SPConnectionController.m in Sources */, BC8C8532100E0A8000D7A129 /* SPTableView.m in Sources */, + 51BB391C25F82B060048CA69 /* SPAppController.swift in Sources */, BC9F0881100FCF2C00A80D32 /* SPFieldEditorController.m in Sources */, 58D2E229101222670063EF1D /* SPTextAndLinkCell.m in Sources */, 1A96E4B72588F34C0055F5F5 /* SecureBookmarkManager.swift in Sources */, From bcfce9f0e07eaf55f0cba7be7c30fa54e5da7fb3 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Tue, 9 Mar 2021 23:53:52 +0100 Subject: [PATCH 10/41] Implement switching tabs and shortcuts --- Source/Controllers/SPAppController.m | 10 +++++++ Source/Controllers/Window/TabManager.swift | 32 ++++++++++++++++++++++ Source/Other/Data/SPConstants.h | 2 ++ Source/Other/Data/SPConstants.m | 2 ++ Source/Views/SPWindow.m | 22 ++++++--------- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index f06cbb936..b65c5c9bc 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -287,6 +287,8 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(externalApplicationWantsToOpenADatabaseConnection:) name:@"ExternalApplicationWantsToOpenADatabaseConnection" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(duplicateConnectionToTab:) name:SPDocumentDuplicateTabNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(switchToPreviousTab:) name:SPWindowSelectPreviousTabNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(switchToNextTab:) name:SPWindowSelectNextTabNotification object:nil]; [sharedSPBundleManager reloadBundles:self]; [self _copyDefaultThemes];; @@ -363,6 +365,14 @@ - (void)externalApplicationWantsToOpenADatabaseConnection:(NSNotification *)noti } } +- (void)switchToPreviousTab:(NSNotification *)notification { + [self.tabManager switchToPreviousTab]; +} + +- (void)switchToNextTab:(NSNotification *)notification { + [self.tabManager switchToNextTab]; +} + - (void)duplicateConnectionToTab:(NSNotification *)notification { NSDictionary *userInfo = [notification userInfo]; diff --git a/Source/Controllers/Window/TabManager.swift b/Source/Controllers/Window/TabManager.swift index 39cbaec13..7dafdafeb 100644 --- a/Source/Controllers/Window/TabManager.swift +++ b/Source/Controllers/Window/TabManager.swift @@ -80,6 +80,38 @@ import AppKit // MARK: - Public API + @objc func switchToPreviousTab() { + // Get index of current tab + guard var index = managedWindows.firstIndex(where: { $0.window.isMainWindow }) else { + return + } + // If index is 0, we are on first tab, try to get the last tab + if index == 0 { + index = managedWindows.count + } + // If index is last window (count - 1), we are on last tab, try to get the first tab + guard let previousWindow = managedWindows[safe: index - 1] else { + return + } + previousWindow.window.order(.above, relativeTo: 0) + } + + @objc func switchToNextTab() { + // Get index of current tab + guard var index = managedWindows.firstIndex(where: { $0.window.isMainWindow }) else { + return + } + // If index is last window (count - 1), we are on last tab, try to get the first tab + if index == managedWindows.count - 1 { + index = -1 + } + // If tab exists, switch to it + guard let nextWindow = managedWindows[safe: index + 1] else { + return + } + nextWindow.window.order(.above, relativeTo: 0) + } + @discardableResult @objc func newWindowForTab() -> SPWindowController { if let existingWindow = mainWindow { diff --git a/Source/Other/Data/SPConstants.h b/Source/Other/Data/SPConstants.h index 4c45f69f4..ffe0cef67 100755 --- a/Source/Other/Data/SPConstants.h +++ b/Source/Other/Data/SPConstants.h @@ -445,6 +445,8 @@ extern NSString *SPDocumentTaskEndNotification; extern NSString *SPDocumentTaskStartNotification; extern NSString *SPDocumentWillCloseNotification; extern NSString *SPDocumentDuplicateTabNotification; +extern NSString *SPWindowSelectPreviousTabNotification; +extern NSString *SPWindowSelectNextTabNotification; extern NSString *SPActivitiesUpdateNotification; extern NSString *SPWindowToolbarDidToggleNotification; extern NSString *SPFieldEditorSheetFont; diff --git a/Source/Other/Data/SPConstants.m b/Source/Other/Data/SPConstants.m index b2d63613b..d8ff85616 100755 --- a/Source/Other/Data/SPConstants.m +++ b/Source/Other/Data/SPConstants.m @@ -250,6 +250,8 @@ - (SPTableViewType)tableViewTypeEnumFromString{ NSString *SPDocumentTaskStartNotification = @"DocumentTaskStarted"; NSString *SPDocumentWillCloseNotification = @"DocumentWillClose"; NSString *SPDocumentDuplicateTabNotification = @"DocumentDuplicateTab"; +NSString *SPWindowSelectPreviousTabNotification = @"WindowSelectPreviousTab"; +NSString *SPWindowSelectNextTabNotification = @"WindowSelectNextTab"; NSString *SPActivitiesUpdateNotification = @"ActivitiesUpdateNotification"; NSString *SPWindowToolbarDidToggleNotification = @"WindowToolbarWasToggledNotification"; NSString *SPFieldEditorSheetFont = @"FieldEditorSheetFont"; diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index a48f020d9..34dc334e1 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -99,35 +99,31 @@ - (void) sendEvent:(NSEvent *)theEvent switch (theCharacter) { - // Alternate keys for switching tabs - ⇧⌘[ and ⇧⌘]. These seem to be standards on some apps, + // Alternate keys for switching tabs - ⇧⌘[ and ⇧⌘]. These seem to be standards on some apps, // including Apple applications under some circumstances case '}': - if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) - { - // TODO: Tabs switching + if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SPWindowSelectNextTabNotification object:nil]; return; } break; case '{': - if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) - { - // TODO: Tabs switching + if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagShift)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SPWindowSelectPreviousTabNotification object:nil]; return; } break; // Also support ⌥⌘← and ⌥⌘→, used in other applications, for maximum compatibility case NSRightArrowFunctionKey: - if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) - { - // TODO: Tabs switching + if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SPWindowSelectNextTabNotification object:nil]; return; } break; case NSLeftArrowFunctionKey: - if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) - { - // TODO: Tabs switching + if (([theEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask) == (NSEventModifierFlagCommand | NSEventModifierFlagOption | NSEventModifierFlagNumericPad | NSEventModifierFlagFunction)) { + [[NSNotificationCenter defaultCenter] postNotificationName:SPWindowSelectPreviousTabNotification object:nil]; return; } break; From 1bf9f9caec90f45fd5c31639a3f4b380dfd87e12 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Wed, 10 Mar 2021 23:26:30 +0100 Subject: [PATCH 11/41] Rename selectedDocument to databaseDocument --- .../MainViewControllers/SPDatabaseDocument.m | 18 +++++----- Source/Controllers/SPAppController.m | 36 +++++++++---------- .../Window/SPWindowController.swift | 12 +++---- Source/Controllers/Window/TabManager.swift | 2 +- .../CategoryAdditions/SPTextViewAdditions.m | 2 +- .../CategoryAdditions/SPWindowAdditions.m | 2 +- Source/Views/SPWindow.m | 7 ++-- Source/Views/TableViews/SPTableView.m | 2 +- 8 files changed, 40 insertions(+), 41 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 59049f75a..ae32192b4 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -2937,24 +2937,24 @@ - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)ret NSMutableDictionary *win = [NSMutableDictionary dictionary]; // Skip not connected docs eg if connection controller is displayed (TODO maybe to be improved) - if (![windowController.selectedTableDocument mySQLVersion]) continue; + if (![windowController.databaseDocument mySQLVersion]) continue; NSMutableDictionary *tabData = [NSMutableDictionary dictionary]; - if([windowController.selectedTableDocument isUntitled]) { + if([windowController.databaseDocument isUntitled]) { // new bundle file name for untitled docs NSString *newName = [NSString stringWithFormat:@"%@.%@", [NSString stringWithNewUUID], SPFileExtensionDefault]; // internal bundle path to store the doc NSString *filePath = [NSString stringWithFormat:@"%@/Contents/%@", fileName, newName]; // save it as temporary spf file inside the bundle with save panel options spfDocData_temp - [windowController.selectedTableDocument saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; - [windowController.selectedTableDocument setIsSavedInBundle:YES]; + [windowController.databaseDocument saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; + [windowController.databaseDocument setIsSavedInBundle:YES]; [tabData setObject:@NO forKey:@"isAbsolutePath"]; [tabData setObject:newName forKey:@"path"]; } else { // save it to the original location and take the file's spfDocData - [windowController.selectedTableDocument saveDocumentWithFilePath:[[windowController.selectedTableDocument fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; + [windowController.databaseDocument saveDocumentWithFilePath:[[windowController.databaseDocument fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; [tabData setObject:@YES forKey:@"isAbsolutePath"]; - [tabData setObject:[[windowController.selectedTableDocument fileURL] path] forKey:@"path"]; + [tabData setObject:[[windowController.databaseDocument fileURL] path] forKey:@"path"]; } [win setObject:NSStringFromRect([[windowController window] frame]) forKey:@"frame"]; [windows addObject:win]; @@ -3568,7 +3568,7 @@ - (void) updateWindowTitle:(id)sender } } - if ([self.parentWindowController selectedTableDocument] == self) { + if ([self.parentWindowController databaseDocument] == self) { [[self.parentWindowController window] setTitle:windowTitle]; } } @@ -4072,7 +4072,7 @@ - (void)tabDidResize [contentViewSplitter setPosition:[[[contentViewSplitter subviews] objectAtIndex:0] bounds].size.width ofDividerAtIndex:0]; // If the task interface is visible, and this tab is frontmost, re-center the task child window - if (_isWorkingLevel && [self.parentWindowController selectedTableDocument] == self) [self centerTaskWindow]; + if (_isWorkingLevel && [self.parentWindowController databaseDocument] == self) [self centerTaskWindow]; } #pragma mark - @@ -4084,7 +4084,7 @@ - (void)tabDidResize - (void)setFileURL:(NSURL *)theURL { spfFileURL = theURL; - if ([self.parentWindowController selectedTableDocument] == self) { + if ([self.parentWindowController databaseDocument] == self) { if (spfFileURL && [spfFileURL isFileURL]) { [[self.parentWindowController window] setRepresentedURL:spfFileURL]; } else { diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index b65c5c9bc..cdbbd2062 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -298,12 +298,12 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { SPWindowController *newWindowController = [self.tabManager replaceTabServiceWithInitialWindow]; if (spfDict) { - [newWindowController.selectedTableDocument setState:spfDict]; + [newWindowController.databaseDocument setState:spfDict]; } // Set autoconnection if appropriate if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAutoConnectToDefault] && secureBookmarkManager.staleBookmarks.count == 0) { - [newWindowController.selectedTableDocument connect]; + [newWindowController.databaseDocument connect]; } } } @@ -360,7 +360,7 @@ - (void)externalApplicationWantsToOpenADatabaseConnection:(NSNotification *)noti NSDictionary *spfStructure = [userInfo objectForKey:@"spfData"]; if (spfStructure) { SPWindowController *windowController = [self.tabManager newWindowForWindow]; - [windowController.selectedTableDocument setState:spfStructure]; + [windowController.databaseDocument setState:spfStructure]; } } } @@ -378,7 +378,7 @@ - (void)duplicateConnectionToTab:(NSNotification *)notification { NSDictionary *userInfo = [notification userInfo]; if (userInfo) { SPWindowController *newWindowController = [self.tabManager newWindowForTab]; - [newWindowController.selectedTableDocument setState:userInfo]; + [newWindowController.databaseDocument setState:userInfo]; } } @@ -528,7 +528,7 @@ - (void)application:(NSApplication *)app openFiles:(NSArray *)filenames - (void)openConnectionFileAtPath:(NSString *)filePath { SPWindowController *windowController = [self.tabManager newWindowForWindow]; - [windowController.selectedTableDocument setStateFromConnectionFile:filePath]; + [windowController.databaseDocument setStateFromConnectionFile:filePath]; [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:filePath]]; } @@ -612,7 +612,7 @@ - (void)openSQLFileAtPath:(NSString *)filePath // Check if at least one document exists. If not, open one. if (![self.tabManager activeWindowController]) { - frontDocument = [self.tabManager newWindowForWindow].selectedTableDocument; + frontDocument = [self.tabManager newWindowForWindow].databaseDocument; [frontDocument initQueryEditorWithString:sqlString]; } else { @@ -715,8 +715,8 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { if ([[newWindowController window] isMiniaturized]) [[newWindowController window] deminiaturize:self]; - [newWindowController.selectedTableDocument setIsSavedInBundle:isBundleFile]; - if (![newWindowController.selectedTableDocument setStateFromConnectionFile:fileName]) { + [newWindowController.databaseDocument setIsSavedInBundle:isBundleFile]; + if (![newWindowController.databaseDocument setStateFromConnectionFile:fileName]) { break; } } @@ -823,7 +823,7 @@ - (void)handleMySQLConnectWithURL:(NSURL *)url { } SPWindowController *windowController = [self.tabManager newWindowForWindow]; - [windowController.selectedTableDocument setState:@{@"connection":details,@"auto_connect": connect} fromFile:NO]; + [windowController.databaseDocument setState:@{@"connection":details,@"auto_connect": connect} fromFile:NO]; } - (void)handleEventWithURL:(NSURL*)url @@ -934,8 +934,8 @@ - (void)handleEventWithURL:(NSURL*)url processDocument = [self frontDocument]; } else { for (SPWindowController *windowController in self.windowControllers) { - if([windowController.selectedTableDocument processID] && [[windowController.selectedTableDocument processID] isEqualToString:passedProcessID]) { - processDocument = windowController.selectedTableDocument; + if([windowController.databaseDocument processID] && [[windowController.databaseDocument processID] isEqualToString:passedProcessID]) { + processDocument = windowController.databaseDocument; goto break_loop; } } @@ -1103,8 +1103,8 @@ - (NSDictionary*)shellEnvironmentForDocument:(NSString*)docUUID { doc = [self frontDocument]; else { for (SPWindowController *windowController in self.windowControllers) { - if ([windowController.selectedTableDocument processID] && [[windowController.selectedTableDocument processID] isEqualToString:docUUID]) { - [env addEntriesFromDictionary:[windowController.selectedTableDocument shellVariables]]; + if ([windowController.databaseDocument processID] && [[windowController.databaseDocument processID] isEqualToString:docUUID]) { + [env addEntriesFromDictionary:[windowController.databaseDocument shellVariables]]; goto break_loop; } } @@ -1250,7 +1250,7 @@ - (SPPreferenceController *)preferenceController * Retrieve the frontmost document; returns nil if not found. */ - (SPDatabaseDocument *)frontDocument { - return [[self.tabManager activeWindowController] selectedTableDocument]; + return [[self.tabManager activeWindowController] databaseDocument]; } /** @@ -1384,7 +1384,7 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende // Iterate through each open window for (SPWindowController *windowController in self.windowControllers) { // Kill any BASH commands which are currently active - for (NSDictionary *cmd in [windowController.selectedTableDocument runningActivities]) { + for (NSDictionary *cmd in [windowController.databaseDocument runningActivities]) { NSInteger pid = [[cmd objectForKey:@"pid"] integerValue]; NSTask *killTask = [[NSTask alloc] init]; @@ -1395,7 +1395,7 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende } // If the connection view is active, mark the favourites for saving - if (![windowController.selectedTableDocument getConnection]) { + if (![windowController.databaseDocument getConnection]) { shouldSaveFavorites = YES; } } @@ -1480,7 +1480,7 @@ - (NSArray *)orderedDocuments for (NSWindow *aWindow in [self orderedWindows]) { if ([[aWindow windowController] isMemberOfClass:[SPWindowController class]]) { - [orderedDocuments addObject:[(SPWindowController *)[aWindow windowController] selectedTableDocument]]; + [orderedDocuments addObject:[(SPWindowController *)[aWindow windowController] databaseDocument]]; } } return orderedDocuments; @@ -1563,7 +1563,7 @@ - (IBAction)duplicateTab:(id)sender { @"password" : @YES }; - NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[self.tabManager.activeWindowController.selectedTableDocument stateIncludingDetails:allStateDetails]]; + NSMutableDictionary *frontState = [NSMutableDictionary dictionaryWithDictionary:[self.tabManager.activeWindowController.databaseDocument stateIncludingDetails:allStateDetails]]; // Ensure it's set to autoconnect [frontState setObject:@YES forKey:@"auto_connect"]; diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index f554c6555..c2cb165a8 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -39,7 +39,7 @@ import SnapKit @objc weak var delegate: SPWindowControllerDelegate? - @objc lazy var selectedTableDocument: SPDatabaseDocument = SPDatabaseDocument(windowController: self) + @objc lazy var databaseDocument: SPDatabaseDocument = SPDatabaseDocument(windowController: self) override func awakeFromNib() { super.awakeFromNib() @@ -52,11 +52,11 @@ import SnapKit } private func setupAppearance() { - selectedTableDocument.didBecomeActiveTabInWindow() - selectedTableDocument.updateWindowTitle(self) + databaseDocument.didBecomeActiveTabInWindow() + databaseDocument.updateWindowTitle(self) - window?.contentView?.addSubview(selectedTableDocument.databaseView()) - selectedTableDocument.databaseView()?.frame = window?.contentView?.frame ?? NSRect(x: 0, y: 0, width: 800, height: 400) + window?.contentView?.addSubview(databaseDocument.databaseView()) + databaseDocument.databaseView()?.frame = window?.contentView?.frame ?? NSRect(x: 0, y: 0, width: 800, height: 400) } } @@ -66,7 +66,7 @@ extension SPWindowController: NSWindowDelegate { /// - Parameter sender: NSWindow instance /// - Returns: true or false public func windowShouldClose(_ sender: NSWindow) -> Bool { - if !selectedTableDocument.parentTabShouldClose() { + if !databaseDocument.parentTabShouldClose() { return false } diff --git a/Source/Controllers/Window/TabManager.swift b/Source/Controllers/Window/TabManager.swift index 7dafdafeb..31fbfd371 100644 --- a/Source/Controllers/Window/TabManager.swift +++ b/Source/Controllers/Window/TabManager.swift @@ -146,7 +146,7 @@ private extension TabManager { windowController.delegate = appController windowController.window?.delegate = appController windowController.showWindow(self) - windowController.selectedTableDocument.didBecomeActiveTabInWindow() + windowController.databaseDocument.didBecomeActiveTabInWindow() return windowController } diff --git a/Source/Other/CategoryAdditions/SPTextViewAdditions.m b/Source/Other/CategoryAdditions/SPTextViewAdditions.m index f5ad7fbb1..7ebfd6206 100644 --- a/Source/Other/CategoryAdditions/SPTextViewAdditions.m +++ b/Source/Other/CategoryAdditions/SPTextViewAdditions.m @@ -792,7 +792,7 @@ - (NSMenu *)menuForEvent:(NSEvent *)event } id windowController = [[NSApp keyWindow] delegate]; - if ([windowController isKindOfClass:[SPWindowController class]] && [[[(SPWindowController *)windowController selectedTableDocument] connectionID] isEqualToString:@"_"]) { + if ([windowController isKindOfClass:[SPWindowController class]] && [[[(SPWindowController *)windowController databaseDocument] connectionID] isEqualToString:@"_"]) { return menu; } diff --git a/Source/Other/CategoryAdditions/SPWindowAdditions.m b/Source/Other/CategoryAdditions/SPWindowAdditions.m index ff35910e4..240ba80b5 100644 --- a/Source/Other/CategoryAdditions/SPWindowAdditions.m +++ b/Source/Other/CategoryAdditions/SPWindowAdditions.m @@ -88,7 +88,7 @@ - (void)swipeWithEvent:(NSEvent *)event { if (![[self delegate] isKindOfClass:[SPWindowController class]]) return; - id frontDoc = [(SPWindowController *)[self delegate] selectedTableDocument]; + id frontDoc = [(SPWindowController *)[self delegate] databaseDocument]; if (frontDoc && [frontDoc isKindOfClass:[SPDatabaseDocument class]] && [frontDoc valueForKeyPath:@"spHistoryControllerInstance"] && ![frontDoc isWorking]) { diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index 34dc334e1..cbda96ae4 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -142,10 +142,9 @@ - (void) sendEvent:(NSEvent *)theEvent * document. This allows undo to be individual per tab rather than shared across the * window. */ -- (NSUndoManager *)undoManager -{ - if ([[self windowController] respondsToSelector:@selector(selectedTableDocument)]) { - return [[[self windowController] selectedTableDocument] undoManager]; +- (NSUndoManager *)undoManager { + if ([[self windowController] isKindOfClass:[SPWindowController class]]) { + return [[(SPWindowController *)[self windowController] databaseDocument] undoManager]; } diff --git a/Source/Views/TableViews/SPTableView.m b/Source/Views/TableViews/SPTableView.m index d8bb83b97..259f12b60 100644 --- a/Source/Views/TableViews/SPTableView.m +++ b/Source/Views/TableViews/SPTableView.m @@ -107,7 +107,7 @@ - (NSMenu *)menuForEvent:(NSEvent *)event SPDatabaseDocument *parentTableDocument = nil; if ([[[[[self window] delegate] class] description] isEqualToString:@"SPWindowController"]) { - parentTableDocument = [(SPWindowController *)[[self window] delegate] selectedTableDocument]; + parentTableDocument = [(SPWindowController *)[[self window] delegate] databaseDocument]; } // If SPDatabaseDocument is performing a task suppress any context menu From 54b8b6a667fe810be03e8cf3ad714bbc574acacf Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 00:11:32 +0100 Subject: [PATCH 12/41] Fix toolbar sizing, fix autosave and restoration, cleanup methods that are not used anymore --- Interfaces/MainWindow.xib | 7 +- .../MainViewControllers/SPDatabaseDocument.h | 4 - .../MainViewControllers/SPDatabaseDocument.m | 101 ++++-------------- Source/Controllers/SPAppController.m | 15 +-- .../Window/SPWindowController.swift | 1 - Source/Controllers/Window/TabManager.swift | 1 - .../CategoryAdditions/SPWindowAdditions.h | 1 - .../CategoryAdditions/SPWindowAdditions.m | 16 --- 8 files changed, 26 insertions(+), 120 deletions(-) diff --git a/Interfaces/MainWindow.xib b/Interfaces/MainWindow.xib index ebc2907a6..1fea1f834 100644 --- a/Interfaces/MainWindow.xib +++ b/Interfaces/MainWindow.xib @@ -13,14 +13,13 @@ - + - - + - + diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index be403c344..0f1a9fcd0 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -418,10 +418,6 @@ - (void)makeKeyDocument; - (BOOL)parentTabShouldClose; - (void)parentTabDidClose; -- (void)willResignActiveTabInWindow; -- (void)didBecomeActiveTabInWindow; -- (void)tabDidBecomeKey; -- (void)tabDidResize; - (void)setIsProcessing:(BOOL)value; - (BOOL)isProcessing; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index ae32192b4..efb984ce0 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -161,6 +161,8 @@ + (void)initialize { - (instancetype)initWithWindowController:(SPWindowController *)windowController { if (self = [super init]) { + _parentWindowController = windowController; + instanceId = atomic_fetch_add(&SPDatabaseDocumentInstanceCounter, 1); _mainNibLoaded = NO; @@ -245,8 +247,6 @@ - (instancetype)initWithWindowController:(SPWindowController *)windowController databaseStructureRetrieval = [[SPDatabaseStructure alloc] initWithDelegate:self]; } - _parentWindowController = windowController; - return self; } @@ -261,7 +261,6 @@ - (void)awakeFromNib // Set collapsible behaviour on the table list so collapsing behaviour handles resize issus [contentViewSplitter setCollapsibleSubviewIndex:0]; - [contentViewSplitter setMaxSize:200.0f ofSubviewAtIndex:0]; // Set a minimum size on both text views on the table info page [tableInfoSplitView setMinSize:20 ofSubviewAtIndex:0]; @@ -327,6 +326,24 @@ - (void)awakeFromNib alterDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseAlterEncodingButton CollationButton:databaseAlterCollationButton]; addDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseEncodingButton CollationButton:databaseCollationButton]; + + // Update the toolbar + [[self.parentWindowController window] setToolbar:mainToolbar]; + + // Update the window's title and represented document + [self updateWindowTitle:self]; + [[self.parentWindowController window] setRepresentedURL:(spfFileURL && [spfFileURL isFileURL] ? spfFileURL : nil)]; + + // Add the progress window to this window + [self centerTaskWindow]; + [[self.parentWindowController window] addChildWindow:taskProgressWindow ordered:NSWindowAbove]; + + // If not connected, update the favorite selection + if (!_isConnected) { + [connectionController updateFavoriteNextKeyView]; + } + + initComplete = YES; } #pragma mark - @@ -3526,7 +3543,7 @@ - (NSWindow *)getCreateTableSyntaxWindow /** * Update the window title. */ -- (void) updateWindowTitle:(id)sender +- (void)updateWindowTitle:(id)sender { // Ensure a call on the main thread if (![NSThread isMainThread]) return [[self onMainThread] updateWindowTitle:sender]; @@ -3568,9 +3585,7 @@ - (void) updateWindowTitle:(id)sender } } - if ([self.parentWindowController databaseDocument] == self) { - [[self.parentWindowController window] setTitle:windowTitle]; - } + [[self.parentWindowController window] setTitle:windowTitle]; } /** @@ -4003,78 +4018,6 @@ - (void)parentTabDidClose [[NSNotificationCenter defaultCenter] removeObserver:self]; } -/** - * Invoked when the parent tab is currently the active tab in the - * window, but is being switched away from, to allow cleaning up - * details in the window. - */ -- (void)willResignActiveTabInWindow { - // Remove the task progress window - [[self.parentWindowController window] removeChildWindow:taskProgressWindow]; - [taskProgressWindow orderOut:self]; -} - -/** - * Invoked when the parent tab became the active tab in the window, - * to allow the window to reflect the contents of this view. - */ -- (void)didBecomeActiveTabInWindow -{ - // Update the toolbar - BOOL toolbarVisible = ![[self.parentWindowController window] toolbar] || [[[self.parentWindowController window] toolbar] isVisible]; - [[self.parentWindowController window] setToolbar:mainToolbar]; - [mainToolbar setVisible:toolbarVisible]; - - // Update the window's title and represented document - [self updateWindowTitle:self]; - [[self.parentWindowController window] setRepresentedURL:(spfFileURL && [spfFileURL isFileURL] ? spfFileURL : nil)]; - - // Add the progress window to this window - [self centerTaskWindow]; - [[self.parentWindowController window] addChildWindow:taskProgressWindow ordered:NSWindowAbove]; - - // If not connected, update the favorite selection - if (!_isConnected) { - [connectionController updateFavoriteNextKeyView]; - } - - initComplete = YES; -} - -/** - * Invoked when the parent tab became the key tab in the application; - * the selected tab in the frontmost window. - */ -- (void)tabDidBecomeKey -{ - // Synchronize Navigator with current active document if Navigator runs in syncMode - if([[SPNavigatorController sharedNavigatorController] syncMode] && [self connectionID] && ![[self connectionID] isEqualToString:@"_"]) { - NSMutableString *schemaPath = [NSMutableString string]; - [schemaPath setString:[self connectionID]]; - if([self database] && [[self database] length]) { - [schemaPath appendString:SPUniqueSchemaDelimiter]; - [schemaPath appendString:[self database]]; - if([self table] && [[self table] length]) { - [schemaPath appendString:SPUniqueSchemaDelimiter]; - [schemaPath appendString:[self table]]; - } - } - [[SPNavigatorController sharedNavigatorController] selectPath:schemaPath]; - } -} - -/** - * Invoked when the document window is resized - */ -- (void)tabDidResize -{ - // Coax the main split view into actually checking its constraints - [contentViewSplitter setPosition:[[[contentViewSplitter subviews] objectAtIndex:0] bounds].size.width ofDividerAtIndex:0]; - - // If the task interface is visible, and this tab is frontmost, re-center the task child window - if (_isWorkingLevel && [self.parentWindowController databaseDocument] == self) [self centerTaskWindow]; -} - #pragma mark - #pragma mark NSDocument compatibility diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index cdbbd2062..f418c0e2f 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -297,6 +297,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { if (![self frontDocument]) { SPWindowController *newWindowController = [self.tabManager replaceTabServiceWithInitialWindow]; + if (spfDict) { [newWindowController.databaseDocument setState:spfDict]; } @@ -669,20 +670,6 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { [self.windowControllers addObject:newWindowController]; NSWindow *newWindow = [newWindowController window]; - // 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"]; - } - - if ([window objectForKey:@"frame"]) - { - [newWindow setFrame:NSRectFromString([window objectForKey:@"frame"]) display:NO]; - } - // Set the window controller as the window's delegate [newWindow setDelegate:newWindowController]; diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index c2cb165a8..9787323f6 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -52,7 +52,6 @@ import SnapKit } private func setupAppearance() { - databaseDocument.didBecomeActiveTabInWindow() databaseDocument.updateWindowTitle(self) window?.contentView?.addSubview(databaseDocument.databaseView()) diff --git a/Source/Controllers/Window/TabManager.swift b/Source/Controllers/Window/TabManager.swift index 31fbfd371..321f8378f 100644 --- a/Source/Controllers/Window/TabManager.swift +++ b/Source/Controllers/Window/TabManager.swift @@ -146,7 +146,6 @@ private extension TabManager { windowController.delegate = appController windowController.window?.delegate = appController windowController.showWindow(self) - windowController.databaseDocument.didBecomeActiveTabInWindow() return windowController } diff --git a/Source/Other/CategoryAdditions/SPWindowAdditions.h b/Source/Other/CategoryAdditions/SPWindowAdditions.h index 82cea7f4a..373f9940f 100644 --- a/Source/Other/CategoryAdditions/SPWindowAdditions.h +++ b/Source/Other/CategoryAdditions/SPWindowAdditions.h @@ -30,7 +30,6 @@ @interface NSWindow (SPWindowAdditions) -- (CGFloat)toolbarHeight; - (void)resizeForContentView:(NSView *)view; @end diff --git a/Source/Other/CategoryAdditions/SPWindowAdditions.m b/Source/Other/CategoryAdditions/SPWindowAdditions.m index 240ba80b5..e4f8331d2 100644 --- a/Source/Other/CategoryAdditions/SPWindowAdditions.m +++ b/Source/Other/CategoryAdditions/SPWindowAdditions.m @@ -35,22 +35,6 @@ @implementation NSWindow (SPWindowAdditions) -/** - * Returns the height of the currently visible toolbar. - */ -- (CGFloat)toolbarHeight -{ - NSRect windowFrame; - CGFloat toolbarHeight = 0.0f; - - if ([self toolbar] && [[self toolbar] isVisible]) { - windowFrame = [NSWindow contentRectForFrameRect:[self frame] styleMask:[self styleMask]]; - toolbarHeight = NSHeight(windowFrame) - NSHeight([[self contentView] frame]); - } - - return toolbarHeight; -} - /** * Resizes this window to the size of the supplied view. */ From 88e6001c7bb227b29d777bb0c3a30ede58d1d286 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 00:18:32 +0100 Subject: [PATCH 13/41] Cleanup methods --- .../DataExport/SPExportController.m | 1 - .../ConnectionView/SPConnectionController.h | 2 +- .../MainViewControllers/SPDatabaseDocument.h | 3 - .../MainViewControllers/SPDatabaseDocument.m | 85 +++++++++---------- .../Preferences/SPPreferenceController.m | 5 +- 5 files changed, 42 insertions(+), 54 deletions(-) diff --git a/Source/Controllers/DataExport/SPExportController.m b/Source/Controllers/DataExport/SPExportController.m index 5568fbdbd..f93954953 100644 --- a/Source/Controllers/DataExport/SPExportController.m +++ b/Source/Controllers/DataExport/SPExportController.m @@ -44,7 +44,6 @@ #import "SPSQLExporter.h" #import "SPXMLExporter.h" #import "SPDotExporter.h" -#import "SPConnectionControllerDelegateProtocol.h" #import "SPExporter.h" #import "SPCSVExporterProtocol.h" #import "SPSQLExporterProtocol.h" diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h index 9e7112c0a..6a0026201 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h @@ -200,7 +200,7 @@ typedef NS_ENUM(NSInteger, SPConnectionTimeZoneMode) { } -@property (readwrite, weak) id delegate; +@property (readwrite, weak) id delegate; @property (readwrite) NSInteger type; @property (readwrite, copy) NSString *name; @property (readwrite, copy) NSString *host; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 0f1a9fcd0..f43015dfe 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -410,19 +410,16 @@ // Toolbar methods - (void)updateWindowTitle:(id)sender; -- (void)setupToolbar; - (NSString *)selectedToolbarItemIdentifier; - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag; // Tab methods - (void)makeKeyDocument; - (BOOL)parentTabShouldClose; -- (void)parentTabDidClose; - (void)setIsProcessing:(BOOL)value; - (BOOL)isProcessing; -- (void)updateParentWindowController:(SPWindowController *)windowController; - (NSWindow *)parentWindowControllerWindow; // Scripting diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index efb984ce0..9ffe2b718 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3941,21 +3941,26 @@ - (void)makeKeyDocument /** * Invoked to determine whether the parent tab is allowed to close */ -- (BOOL)parentTabShouldClose -{ +- (BOOL)parentTabShouldClose { // If no connection is available, always return YES. Covers initial setup and disconnections. - if(!_isConnected) return YES; + if(!_isConnected) { + return YES; + } // If tasks are active, return NO to allow tasks to complete - if (_isWorkingLevel) return NO; + if (_isWorkingLevel) { + return NO; + } // If the table list considers itself to be working, return NO. This catches open alerts, and // edits in progress in various views. - if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) return NO; + if (![tablesListInstance selectionShouldChangeInTableView:nil]) { + return NO; + } // Auto-save spf file based connection and return if the save was not successful - if([self fileURL] && [[[self fileURL] path] length] && ![self isUntitled]) { + if ([self fileURL] && [[[self fileURL] path] length] && ![self isUntitled]) { BOOL isSaved = [self saveDocumentWithFilePath:nil inBackground:YES onlyPreferences:YES contextInfo:nil]; if (isSaved) { [[SPQueryController sharedQueryController] removeRegisteredDocumentWithFileURL:[self fileURL]]; @@ -3965,7 +3970,7 @@ - (BOOL)parentTabShouldClose } // Terminate all running BASH commands - for(NSDictionary* cmd in [self runningActivities]) { + for (NSDictionary* cmd in [self runningActivities]) { NSInteger pid = [[cmd objectForKey:@"pid"] integerValue]; NSTask *killTask = [[NSTask alloc] init]; [killTask setLaunchPath:@"/bin/sh"]; @@ -3983,41 +3988,6 @@ - (BOOL)parentTabShouldClose return YES; } -/** - * Invoked when the parent tab is about to close - */ -- (void)parentTabDidClose -{ - // if tab closed and there is text in the query view, safe to history - NSString *queryString = [self->customQueryTextView.textStorage string]; - - if([queryString length] > 0){ - [[SPQueryController sharedQueryController] addHistory:queryString forFileURL:[self fileURL]]; - } - - // Cancel autocompletion trigger - if([prefs boolForKey:SPCustomQueryAutoComplete]) { - [NSObject cancelPreviousPerformRequestsWithTarget:[customQueryInstance valueForKeyPath:@"textView"] - selector:@selector(doAutoCompletion) - object:nil]; - } - if([prefs boolForKey:SPCustomQueryUpdateAutoHelp]) { - [NSObject cancelPreviousPerformRequestsWithTarget:[customQueryInstance valueForKeyPath:@"textView"] - selector:@selector(autoHelp) - object:nil]; - } - - [mySQLConnection setDelegate:nil]; - if (_isConnected) { - [self closeConnection]; - } else { - [connectionController cancelConnection:self]; - } - if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole:self]; - [createTableSyntaxWindow orderOut:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - #pragma mark - #pragma mark NSDocument compatibility @@ -6482,11 +6452,34 @@ - (void)closeAndDisconnect [theParentWindow setAlphaValue:0.0f]; [theParentWindow performSelector:@selector(close) withObject:nil afterDelay:1.0]; - [self parentTabDidClose]; -} + // if tab closed and there is text in the query view, safe to history + NSString *queryString = [self->customQueryTextView.textStorage string]; + + if([queryString length] > 0){ + [[SPQueryController sharedQueryController] addHistory:queryString forFileURL:[self fileURL]]; + } -- (void)updateParentWindowController:(SPWindowController *)windowController { - self.parentWindowController = windowController; + // Cancel autocompletion trigger + if([prefs boolForKey:SPCustomQueryAutoComplete]) { + [NSObject cancelPreviousPerformRequestsWithTarget:[customQueryInstance valueForKeyPath:@"textView"] + selector:@selector(doAutoCompletion) + object:nil]; + } + if([prefs boolForKey:SPCustomQueryUpdateAutoHelp]) { + [NSObject cancelPreviousPerformRequestsWithTarget:[customQueryInstance valueForKeyPath:@"textView"] + selector:@selector(autoHelp) + object:nil]; + } + + [mySQLConnection setDelegate:nil]; + if (_isConnected) { + [self closeConnection]; + } else { + [connectionController cancelConnection:self]; + } + if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole:self]; + [createTableSyntaxWindow orderOut:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (NSWindow *)parentWindowControllerWindow { diff --git a/Source/Controllers/Preferences/SPPreferenceController.m b/Source/Controllers/Preferences/SPPreferenceController.m index 4634ec576..49b16880c 100644 --- a/Source/Controllers/Preferences/SPPreferenceController.m +++ b/Source/Controllers/Preferences/SPPreferenceController.m @@ -40,7 +40,6 @@ @interface SPPreferenceController () -- (void)_setupToolbar; - (void)_resizeWindowForContentView:(NSView *)view; @end @@ -71,7 +70,7 @@ - (instancetype)init */ - (void)windowDidLoad { - [self _setupToolbar]; + [self setupToolbar]; if (@available(macOS 10.14, *)) { [appearancePopUp setEnabled:YES]; @@ -156,7 +155,7 @@ - (void)changeDefaultFont:(id)sender /** * Constructs the preferences' window toolbar. */ -- (void)_setupToolbar +- (void)setupToolbar { toolbar = [[NSToolbar alloc] initWithIdentifier:@"Preference Toolbar"]; From db00d6fe72692e87d76a89b5d29a9b47db9cea4e Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 00:22:36 +0100 Subject: [PATCH 14/41] Don't store dbview in property --- .../ConnectionView/SPConnectionController.h | 1 - .../ConnectionView/SPConnectionController.m | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h index 6a0026201..f74e4f8f7 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h @@ -60,7 +60,6 @@ typedef NS_ENUM(NSInteger, SPConnectionTimeZoneMode) { SPMySQLConnection *mySQLConnection; SPKeychain *keychain; - NSView *databaseConnectionSuperview; NSSplitView *databaseConnectionView; NSOpenPanel *keySelectionPanel; diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 9f731a67c..c37120623 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -3201,7 +3201,6 @@ - (instancetype)initWithDocument:(SPDatabaseDocument *)document // Weak reference dbDocument = document; - databaseConnectionSuperview = [dbDocument databaseView]; databaseConnectionView = dbDocument->contentViewSplitter; @@ -3247,7 +3246,7 @@ - (instancetype)initWithDocument:(SPDatabaseDocument *)document // Hide the main view and position and display the connection view [databaseConnectionView setHidden:YES]; [connectionView setFrame:[databaseConnectionView frame]]; - [databaseConnectionSuperview addSubview:connectionView]; + [[dbDocument databaseView] addSubview:connectionView]; // Set up the splitview [connectionSplitView setMinSize:150.f ofSubviewAtIndex:0]; From 250814d6a24c3b8f1875e1defaec005329de0c62 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 00:24:54 +0100 Subject: [PATCH 15/41] Remove simple method --- .../MainViewControllers/SPDatabaseDocument.h | 1 - .../MainViewControllers/SPDatabaseDocument.m | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index f43015dfe..1b2ad7c05 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -414,7 +414,6 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag; // Tab methods -- (void)makeKeyDocument; - (BOOL)parentTabShouldClose; - (void)setIsProcessing:(BOOL)value; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 9ffe2b718..cf86df02f 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3929,15 +3929,6 @@ - (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem #pragma mark - #pragma mark Tab methods -/** - * Make this document's window frontmost in the application, - * and ensure this tab is selected. - */ -- (void)makeKeyDocument -{ - [[[self.parentWindowController window] onMainThread] makeKeyAndOrderFront:self]; -} - /** * Invoked to determine whether the parent tab is allowed to close */ @@ -6399,9 +6390,7 @@ - (SPMySQLConnectionLostDecision)connectionLost:(id)connection if ([[self.parentWindowController window] isMiniaturized]) { [[self.parentWindowController window] deminiaturize:self]; } - - // Ensure the window and tab are frontmost - [self makeKeyDocument]; + [[self parentWindowControllerWindow] orderWindow:NSWindowAbove relativeTo:0]; // Display the connection error dialog and wait for the return code [[self.parentWindowController window] beginSheet:connectionErrorDialog completionHandler:nil]; From fe4272d009b18cf97116abcca21a368e488c1d2b Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 12:02:30 +0100 Subject: [PATCH 16/41] Remove windows from spappcontroller, move code that shouldn't be part of spdatabase document to app controller, fix spfs association, fix reopening spfs --- Resources/Plists/Info.plist | 16 +- .../MainViewControllers/SPDatabaseDocument.m | 147 ++------------ Source/Controllers/SPAppController.h | 1 - Source/Controllers/SPAppController.m | 186 +++++++++++++++--- Source/Controllers/SPAppController.swift | 6 +- .../Window/SPWindowController.swift | 13 +- Source/Controllers/Window/TabManager.swift | 9 +- Source/Other/Data/SPConstants.h | 1 + Source/Other/Data/SPConstants.m | 1 + 9 files changed, 200 insertions(+), 180 deletions(-) diff --git a/Resources/Plists/Info.plist b/Resources/Plists/Info.plist index 74f258766..2faa08107 100644 --- a/Resources/Plists/Info.plist +++ b/Resources/Plists/Info.plist @@ -2,6 +2,8 @@ + AppCenterApplicationForwarderEnabled + CFBundleDevelopmentRegion English CFBundleDocumentTypes @@ -27,7 +29,7 @@ Owner LSItemContentTypes - com.sequel-ace.sequel-ace.spf + com.sequelpro.SequelPro com.sequel-ace.sequel-ace.spf NSDocumentClass @@ -55,7 +57,7 @@ LSItemContentTypes com.sequelpro.SequelPro.spfs - com.google.code.sequel-pro.spfs + com.sequel-ace.sequel-ace.spfs LSTypeIsPackage @@ -226,23 +228,23 @@ NSExceptionDomains - github.com + appcenter.ms NSExceptionAllowsInsecureHTTPLoads NSExceptionMinimumTLSVersion - TLSv1.3 + TLSv1.2 NSIncludeSubdomains NSRequiresCertificateTransparency - appcenter.ms + github.com NSExceptionAllowsInsecureHTTPLoads NSExceptionMinimumTLSVersion - TLSv1.2 + TLSv1.3 NSIncludeSubdomains NSRequiresCertificateTransparency @@ -496,7 +498,5 @@ - AppCenterApplicationForwarderEnabled - diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index cf86df02f..f017c12a0 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -2850,7 +2850,7 @@ - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)ret NSError *error = nil; // Save file as SQL file by using the chosen encoding - if(contextInfo == @"saveSQLfile") { + if (contextInfo == @"saveSQLfile") { [prefs setInteger:[[encodingPopUp selectedItem] tag] forKey:SPLastSQLFileEncoding]; [prefs setObject:[fileName lastPathComponent] forKey:@"lastSqlFileName"]; @@ -2861,148 +2861,35 @@ - (void)saveConnectionPanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)ret encoding:[[encodingPopUp selectedItem] tag] error:&error]; - if(error != nil) { + if (error != nil) { NSAlert *errorAlert = [NSAlert alertWithError:error]; [errorAlert runModal]; } - [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:fileName]]; - return; - } - // Save connection and session as SPF file - else if(contextInfo == @"saveSPFfile" || contextInfo == @"saveSPFfileAndClose") { + } else if(contextInfo == @"saveSPFfile" || contextInfo == @"saveSPFfileAndClose") { // Save changes of saveConnectionEncryptString [[saveConnectionEncryptString window] makeFirstResponder:[[saveConnectionEncryptString window] initialFirstResponder]]; [self saveDocumentWithFilePath:fileName inBackground:NO onlyPreferences:NO contextInfo:nil]; - if(contextInfo == @"saveSPFfileAndClose") [self closeAndDisconnect]; - } - - // Save all open windows including all tabs as session - else if(contextInfo == @"saveSession" || contextInfo == @"saveAsSession") { - - // Sub-folder 'Contents' will contain all untitled connection as single window or tab. - // info.plist will contain the opened structure (windows and tabs for each window). Each connection - // is linked to a saved spf file either in 'Contents' for unTitled ones or already saved spf files. - - if(contextInfo == @"saveAsSession" && [SPAppDelegate sessionURL]) fileName = [[SPAppDelegate sessionURL] path]; - - if(!fileName || ![fileName length]) return; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - - // If bundle exists remove it - if([fileManager fileExistsAtPath:fileName]) { - [fileManager removeItemAtPath:fileName error:&error]; - if(error != nil) { - NSAlert *errorAlert = [NSAlert alertWithError:error]; - [errorAlert runModal]; - return; - } - } - - [fileManager createDirectoryAtPath:fileName withIntermediateDirectories:YES attributes:nil error:&error]; - - if(error != nil) { - NSAlert *errorAlert = [NSAlert alertWithError:error]; - [errorAlert runModal]; - return; - } - - [fileManager createDirectoryAtPath:[NSString stringWithFormat:@"%@/Contents", fileName] withIntermediateDirectories:YES attributes:nil error:&error]; - - if(error != nil) { - NSAlert *errorAlert = [NSAlert alertWithError:error]; - [errorAlert runModal]; - return; - } - - NSMutableDictionary *info = [NSMutableDictionary dictionary]; - NSMutableArray *windows = [NSMutableArray array]; - - // retrieve save panel data for passing them to each doc - NSMutableDictionary *spfDocData_temp = [NSMutableDictionary dictionary]; - if(contextInfo == @"saveAsSession") { - [spfDocData_temp addEntriesFromDictionary:[SPAppDelegate spfSessionDocData]]; - } else { - [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionEncrypt state]==NSOnState) ? YES : NO ] forKey:@"encrypted"]; - if([[spfDocData_temp objectForKey:@"encrypted"] boolValue]) [spfDocData_temp setObject:[saveConnectionEncryptString stringValue] forKey:@"e_string"]; - [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionAutoConnect state]==NSOnState) ? YES : NO ] forKey:@"auto_connect"]; - [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionSavePassword state]==NSOnState) ? YES : NO ] forKey:@"save_password"]; - [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionIncludeData state]==NSOnState) ? YES : NO ] forKey:@"include_session"]; - [spfDocData_temp setObject:[NSNumber numberWithBool:([saveConnectionIncludeQuery state]==NSOnState) ? YES : NO ] forKey:@"save_editor_content"]; - - // Save the session's accessory view settings - [SPAppDelegate setSpfSessionDocData:spfDocData_temp]; - } - - [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"encrypted"] boolValue]] forKey:@"encrypted"]; - [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"auto_connect"] boolValue]] forKey:@"auto_connect"]; - [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"save_password"] boolValue]] forKey:@"save_password"]; - [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"include_session"] boolValue]] forKey:@"include_session"]; - [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"save_editor_content"] boolValue]] forKey:@"save_editor_content"]; - [info setObject:@1 forKey:SPFVersionKey]; - [info setObject:@"connection bundle" forKey:SPFFormatKey]; - - // Loop through all windows - for (SPWindowController *windowController in [SPAppDelegate windowControllers]) { - - // First window is always the currently key window - NSMutableDictionary *win = [NSMutableDictionary dictionary]; - - // Skip not connected docs eg if connection controller is displayed (TODO maybe to be improved) - if (![windowController.databaseDocument mySQLVersion]) continue; - - NSMutableDictionary *tabData = [NSMutableDictionary dictionary]; - if([windowController.databaseDocument isUntitled]) { - // new bundle file name for untitled docs - NSString *newName = [NSString stringWithFormat:@"%@.%@", [NSString stringWithNewUUID], SPFileExtensionDefault]; - // internal bundle path to store the doc - NSString *filePath = [NSString stringWithFormat:@"%@/Contents/%@", fileName, newName]; - // save it as temporary spf file inside the bundle with save panel options spfDocData_temp - [windowController.databaseDocument saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; - [windowController.databaseDocument setIsSavedInBundle:YES]; - [tabData setObject:@NO forKey:@"isAbsolutePath"]; - [tabData setObject:newName forKey:@"path"]; - } else { - // save it to the original location and take the file's spfDocData - [windowController.databaseDocument saveDocumentWithFilePath:[[windowController.databaseDocument fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; - [tabData setObject:@YES forKey:@"isAbsolutePath"]; - [tabData setObject:[[windowController.databaseDocument fileURL] path] forKey:@"path"]; - } - [win setObject:NSStringFromRect([[windowController window] frame]) forKey:@"frame"]; - [windows addObject:win]; - } - [info setObject:windows forKey:@"windows"]; - - error = nil; - - NSData *plist = [NSPropertyListSerialization dataWithPropertyList:info - format:NSPropertyListXMLFormat_v1_0 - options:0 - error:&error]; - - if (error) { - [NSAlert createWarningAlertWithTitle:NSLocalizedString(@"Error while converting session data", @"error while converting session data") message:[error localizedDescription] callback:nil]; - return; - } - - [plist writeToFile:[NSString stringWithFormat:@"%@/info.plist", fileName] options:NSAtomicWrite error:&error]; - - if (error != nil){ - NSAlert *errorAlert = [NSAlert alertWithError:error]; - [errorAlert runModal]; - - return; + if (contextInfo == @"saveSPFfileAndClose") { + [self closeAndDisconnect]; } - [SPAppDelegate setSessionURL:fileName]; - - // Register spfs bundle in Recent Files - [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:fileName]]; + // Save all open windows including all tabs as session + } else if (contextInfo == @"saveSession" || contextInfo == @"saveAsSession") { + NSDictionary *userInfo = @{ + @"contextInfo": (__bridge NSString *)contextInfo, + @"encrypted": [NSNumber numberWithBool:[saveConnectionEncrypt state] == NSOnState], + @"saveConnectionEncryptString": [saveConnectionEncryptString stringValue], + @"auto_connect": [NSNumber numberWithBool:[saveConnectionAutoConnect state] == NSOnState], + @"save_password": [NSNumber numberWithBool:[saveConnectionSavePassword state] == NSOnState], + @"include_session": [NSNumber numberWithBool:[saveConnectionIncludeData state] == NSOnState], + @"save_editor_content": [NSNumber numberWithBool:[saveConnectionIncludeQuery state] == NSOnState] + }; + [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentSaveToSPFNotification object:fileName userInfo:userInfo]; } } } diff --git a/Source/Controllers/SPAppController.h b/Source/Controllers/SPAppController.h index c626ce3fb..992aae069 100755 --- a/Source/Controllers/SPAppController.h +++ b/Source/Controllers/SPAppController.h @@ -55,7 +55,6 @@ } @property (readwrite, copy) NSString *lastBundleBlobFilesDirectory; -@property (nonatomic, strong, readonly) NSMutableArray *windowControllers; @property (nonatomic, strong) NSMutableArray *sshProcessIDs; @property (weak) IBOutlet NSView *staleBookmarkHelpView; diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index f418c0e2f..ff9c915cd 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -77,7 +77,6 @@ - (void)checkForNewVersionFromMenu; @property (readwrite, strong) NSFileManager *fileManager; @property (readwrite, strong) SPBundleManager *sharedSPBundleManager; -@property (nonatomic, strong, readwrite) NSMutableArray *windowControllers; @property (nonatomic, strong) TabManager *tabManager; @@ -103,7 +102,6 @@ - (instancetype)init aboutController = nil; lastBundleBlobFilesDirectory = nil; _spfSessionDocData = [[NSMutableDictionary alloc] init]; - _windowControllers = [[NSMutableArray alloc] init]; runningActivitiesArray = [[NSMutableArray alloc] init]; sshProcessIDs = [[NSMutableArray alloc] init]; @@ -289,6 +287,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(duplicateConnectionToTab:) name:SPDocumentDuplicateTabNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(switchToPreviousTab:) name:SPWindowSelectPreviousTabNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(switchToNextTab:) name:SPWindowSelectNextTabNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveConnectionsToSPF:) name:SPDocumentSaveToSPFNotification object:nil]; [sharedSPBundleManager reloadBundles:self]; [self _copyDefaultThemes];; @@ -383,6 +382,138 @@ - (void)duplicateConnectionToTab:(NSNotification *)notification { } } +- (void)saveConnectionsToSPF:(NSNotification *)notification { + + NSString *fileName = [notification object]; + NSError *error = nil; + NSString *contextInfo = [[notification userInfo] objectForKey:@"contextInfo"]; + NSNumber *encrypted = [[notification userInfo] objectForKey:@"encrypted"]; + NSString *saveConnectionEncryptString = [[notification userInfo] objectForKey:@"saveConnectionEncryptString"]; + NSNumber *auto_connect = [[notification userInfo] objectForKey:@"auto_connect"]; + NSNumber *save_password = [[notification userInfo] objectForKey:@"save_password"]; + NSNumber *include_session = [[notification userInfo] objectForKey:@"include_session"]; + NSNumber *save_editor_content = [[notification userInfo] objectForKey:@"save_editor_content"]; + + // Sub-folder 'Contents' will contain all untitled connection as single window or tab. + // info.plist will contain the opened structure (windows and tabs for each window). Each connection + // is linked to a saved spf file either in 'Contents' for unTitled ones or already saved spf files. + + if ([contextInfo isEqual:@"saveAsSession"] && [self sessionURL]) { + fileName = [[self sessionURL] path]; + } + + if(!fileName || ![fileName length]) { + return; + } + + // If bundle exists remove it + if([fileManager fileExistsAtPath:fileName]) { + [fileManager removeItemAtPath:fileName error:&error]; + if(error != nil) { + NSAlert *errorAlert = [NSAlert alertWithError:error]; + [errorAlert runModal]; + return; + } + } + + [fileManager createDirectoryAtPath:fileName withIntermediateDirectories:YES attributes:nil error:&error]; + + if (error != nil) { + [[NSAlert alertWithError:error] runModal]; + return; + } + + [fileManager createDirectoryAtPath:[NSString stringWithFormat:@"%@/Contents", fileName] withIntermediateDirectories:YES attributes:nil error:&error]; + + if (error != nil) { + [[NSAlert alertWithError:error] runModal]; + return; + } + + NSMutableDictionary *info = [NSMutableDictionary dictionary]; + NSMutableArray *windows = [NSMutableArray array]; + + // retrieve save panel data for passing them to each doc + NSMutableDictionary *spfDocData_temp = [NSMutableDictionary dictionary]; + if ([contextInfo isEqualTo:@"saveAsSession"]) { + [spfDocData_temp addEntriesFromDictionary:[self spfSessionDocData]]; + } else { + [spfDocData_temp setObject:encrypted forKey:@"encrypted"]; + if ([[spfDocData_temp objectForKey:@"encrypted"] boolValue]) { + [spfDocData_temp setObject:saveConnectionEncryptString forKey:@"e_string"]; + } + [spfDocData_temp setObject:auto_connect forKey:@"auto_connect"]; + [spfDocData_temp setObject:save_password forKey:@"save_password"]; + [spfDocData_temp setObject:include_session forKey:@"include_session"]; + [spfDocData_temp setObject:save_editor_content forKey:@"save_editor_content"]; + + // Save the session's accessory view settings + [self setSpfSessionDocData:spfDocData_temp]; + } + + [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"encrypted"] boolValue]] forKey:@"encrypted"]; + [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"auto_connect"] boolValue]] forKey:@"auto_connect"]; + [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"save_password"] boolValue]] forKey:@"save_password"]; + [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"include_session"] boolValue]] forKey:@"include_session"]; + [info setObject:[NSNumber numberWithBool:[[spfDocData_temp objectForKey:@"save_editor_content"] boolValue]] forKey:@"save_editor_content"]; + [info setObject:@1 forKey:SPFVersionKey]; + [info setObject:@"connection bundle" forKey:SPFFormatKey]; + + // Loop through all windows + for (SPWindowController *windowController in [self.tabManager windowControllers]) { + + // First window is always the currently key window + NSMutableDictionary *win = [NSMutableDictionary dictionary]; + + // Skip not connected docs eg if connection controller is displayed (TODO maybe to be improved) + if (![windowController.databaseDocument mySQLVersion]) continue; + + NSMutableDictionary *tabData = [NSMutableDictionary dictionary]; + if([windowController.databaseDocument isUntitled]) { + // new bundle file name for untitled docs + NSString *newName = [NSString stringWithFormat:@"%@.%@", [NSString stringWithNewUUID], SPFileExtensionDefault]; + // internal bundle path to store the doc + NSString *filePath = [NSString stringWithFormat:@"%@/Contents/%@", fileName, newName]; + // save it as temporary spf file inside the bundle with save panel options spfDocData_temp + [windowController.databaseDocument saveDocumentWithFilePath:filePath inBackground:NO onlyPreferences:NO contextInfo:[NSDictionary dictionaryWithDictionary:spfDocData_temp]]; + [windowController.databaseDocument setIsSavedInBundle:YES]; + [tabData setObject:@NO forKey:@"isAbsolutePath"]; + [tabData setObject:newName forKey:@"path"]; + } else { + // save it to the original location and take the file's spfDocData + [windowController.databaseDocument saveDocumentWithFilePath:[[windowController.databaseDocument fileURL] path] inBackground:YES onlyPreferences:NO contextInfo:nil]; + [tabData setObject:@YES forKey:@"isAbsolutePath"]; + [tabData setObject:[[windowController.databaseDocument fileURL] path] forKey:@"path"]; + } + [win setObject:NSStringFromRect([[windowController window] frame]) forKey:@"frame"]; + [windows addObject:win]; + } + [info setObject:windows forKey:@"windows"]; + + error = nil; + + NSData *plist = [NSPropertyListSerialization dataWithPropertyList:info format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]; + + if (error) { + [NSAlert createWarningAlertWithTitle:NSLocalizedString(@"Error while converting session data", @"error while converting session data") message:[error localizedDescription] callback:nil]; + return; + } + + [plist writeToFile:[NSString stringWithFormat:@"%@/info.plist", fileName] options:NSAtomicWrite error:&error]; + + if (error != nil){ + NSAlert *errorAlert = [NSAlert alertWithError:error]; + [errorAlert runModal]; + + return; + } + + [self setSessionURL:fileName]; + + // Register spfs bundle in Recent Files + [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:[NSURL fileURLWithPath:fileName]]; +} + /** * Menu item validation. */ @@ -659,15 +790,14 @@ - (void)openSessionBundleAtPath:(NSString *)filePath { [spfsDocData setObject:[NSNumber numberWithBool:[[spfs objectForKey:@"save_editor_content"] boolValue]] forKey:@"save_editor_content"]; // Set global session properties - [SPAppDelegate setSpfSessionDocData:spfsDocData]; - [SPAppDelegate setSessionURL:filePath]; + [self setSpfSessionDocData:spfsDocData]; + [self setSessionURL:filePath]; // Loop through each defined window in reversed order to reconstruct the last active window for (NSDictionary *window in [[[spfs objectForKey:@"windows"] reverseObjectEnumerator] allObjects]) { // Create a new window controller, and set up a new connection view within it. - SPWindowController *newWindowController = [[SPWindowController alloc] initWithWindowNibName:@"MainWindow"]; - [newWindowController showWindow:self]; - [self.windowControllers addObject:newWindowController]; + + SPWindowController *newWindowController = [self.tabManager newWindowForWindow]; NSWindow *newWindow = [newWindowController window]; // Set the window controller as the window's delegate @@ -916,17 +1046,14 @@ - (void)handleEventWithURL:(NSURL*)url // Try to find the SPDatabaseDocument which sent the the url scheme command // For speed check the front most first otherwise iterate through all - if(passedProcessID && [passedProcessID length]) { + if (passedProcessID && [passedProcessID length]) { if ([activeProcessID isEqualToString:passedProcessID]) { processDocument = [self frontDocument]; } else { - for (SPWindowController *windowController in self.windowControllers) { - if([windowController.databaseDocument processID] && [[windowController.databaseDocument processID] isEqualToString:passedProcessID]) { - processDocument = windowController.databaseDocument; - goto break_loop; - } + SPWindowController *windowController = [self.tabManager windowControllerWithDocumentWithProcessID:passedProcessID]; + if (windowController) { + processDocument = windowController.databaseDocument; } - break_loop: /* breaking two levels of foreach */; } } @@ -1086,16 +1213,13 @@ - (NSString*)doSQLSyntaxHighlightForString:(NSString*)sqlText cssLike:(BOOL)cssL - (NSDictionary*)shellEnvironmentForDocument:(NSString*)docUUID { NSMutableDictionary *env = [NSMutableDictionary dictionary]; SPDatabaseDocument *doc; - if(docUUID == nil) + if (docUUID == nil) { doc = [self frontDocument]; - else { - for (SPWindowController *windowController in self.windowControllers) { - if ([windowController.databaseDocument processID] && [[windowController.databaseDocument processID] isEqualToString:docUUID]) { - [env addEntriesFromDictionary:[windowController.databaseDocument shellVariables]]; - goto break_loop; - } + } else { + SPWindowController *windowController = [self.tabManager windowControllerWithDocumentWithProcessID:docUUID]; + if (windowController) { + [env addEntriesFromDictionary:[windowController.databaseDocument shellVariables]]; } - break_loop: /* breaking two levels of foreach */; } id firstResponder = [[NSApp keyWindow] firstResponder]; @@ -1222,6 +1346,18 @@ - (IBAction)openPreferences:(id)sender [prefsController showWindow:self]; } +- (IBAction)import:(id)sender { + [[[self.tabManager activeWindowController] databaseDocument] import:sender]; +} + +- (IBAction)importFromClipboard:(id)sender { + [[[self.tabManager activeWindowController] databaseDocument] importFromClipboard:sender]; +} + +- (IBAction)saveConnectionSheet:(id)sender { + [[[self.tabManager activeWindowController] databaseDocument] saveConnectionSheet:sender]; +} + #pragma mark - #pragma mark Accessors @@ -1369,7 +1505,7 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende } // Iterate through each open window - for (SPWindowController *windowController in self.windowControllers) { + for (SPWindowController *windowController in [self.tabManager windowControllers]) { // Kill any BASH commands which are currently active for (NSDictionary *cmd in [windowController.databaseDocument runningActivities]) { NSInteger pid = [[cmd objectForKey:@"pid"] integerValue]; @@ -1563,7 +1699,9 @@ - (IBAction)duplicateTab:(id)sender { - (void)windowWillClose:(NSNotification *)notification { id window = notification.object; - if (!window) { return; } + if (!window) { + return; + } if (window == aboutController.window) { aboutController.window.delegate = nil; diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 06d7dc9d6..dbefe4e98 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -8,8 +8,6 @@ import AppKit -extension SPAppController: SPWindowControllerDelegate { - func windowControllerDidClose(_ windowController: SPWindowController) { - windowControllers.remove(windowController) - } +extension SPAppController { + } diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index 9787323f6..cdcf45920 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -31,14 +31,8 @@ import Cocoa import SnapKit -@objc protocol SPWindowControllerDelegate: AnyObject { - func windowControllerDidClose(_ windowController: SPWindowController) -} - @objc final class SPWindowController: NSWindowController { - @objc weak var delegate: SPWindowControllerDelegate? - @objc lazy var databaseDocument: SPDatabaseDocument = SPDatabaseDocument(windowController: self) override func awakeFromNib() { @@ -60,20 +54,15 @@ import SnapKit } extension SPWindowController: NSWindowDelegate { - /// Determine whether the window is permitted to close. - /// Go through the tabs in this window, and ask the database connection view in each one if it can be closed, returning YES only if all can be closed. - /// - Parameter sender: NSWindow instance - /// - Returns: true or false public func windowShouldClose(_ sender: NSWindow) -> Bool { if !databaseDocument.parentTabShouldClose() { return false } - if let appDelegate = NSApp.delegate as? SPAppController, appDelegate.sessionURL() != nil, appDelegate.windowControllers.count == 1 { + if let appDelegate = NSApp.delegate as? SPAppController, appDelegate.sessionURL() != nil { appDelegate.setSessionURL(nil) appDelegate.setSpfSessionDocData(nil) } - delegate?.windowControllerDidClose(self) return true } } diff --git a/Source/Controllers/Window/TabManager.swift b/Source/Controllers/Window/TabManager.swift index 321f8378f..901e6f316 100644 --- a/Source/Controllers/Window/TabManager.swift +++ b/Source/Controllers/Window/TabManager.swift @@ -68,6 +68,10 @@ import AppKit return managedWindows.first { $0.window.isMainWindow }?.windowController } + @objc var windowControllers: [SPWindowController] { + return managedWindows.compactMap { $0.windowController} + } + weak var appController: SPAppController? // MARK: - Lifecycle @@ -136,6 +140,10 @@ import AppKit addManagedWindow(windowController: windowController) return windowController } + + @objc func windowControllerWithDocument(processID: String) -> SPWindowController? { + return managedWindows.first(where: { $0.windowController.databaseDocument.processID == processID })?.windowController + } } // MARK: - Private API @@ -143,7 +151,6 @@ import AppKit private extension TabManager { func createNewWindowController() -> SPWindowController { let windowController = SPWindowController(windowNibName: "MainWindow") - windowController.delegate = appController windowController.window?.delegate = appController windowController.showWindow(self) return windowController diff --git a/Source/Other/Data/SPConstants.h b/Source/Other/Data/SPConstants.h index ffe0cef67..b1f204e24 100755 --- a/Source/Other/Data/SPConstants.h +++ b/Source/Other/Data/SPConstants.h @@ -445,6 +445,7 @@ extern NSString *SPDocumentTaskEndNotification; extern NSString *SPDocumentTaskStartNotification; extern NSString *SPDocumentWillCloseNotification; extern NSString *SPDocumentDuplicateTabNotification; +extern NSString *SPDocumentSaveToSPFNotification; extern NSString *SPWindowSelectPreviousTabNotification; extern NSString *SPWindowSelectNextTabNotification; extern NSString *SPActivitiesUpdateNotification; diff --git a/Source/Other/Data/SPConstants.m b/Source/Other/Data/SPConstants.m index d8ff85616..d6d85f681 100755 --- a/Source/Other/Data/SPConstants.m +++ b/Source/Other/Data/SPConstants.m @@ -250,6 +250,7 @@ - (SPTableViewType)tableViewTypeEnumFromString{ NSString *SPDocumentTaskStartNotification = @"DocumentTaskStarted"; NSString *SPDocumentWillCloseNotification = @"DocumentWillClose"; NSString *SPDocumentDuplicateTabNotification = @"DocumentDuplicateTab"; +NSString *SPDocumentSaveToSPFNotification = @"DocumentSaveToSPFNotification"; NSString *SPWindowSelectPreviousTabNotification = @"WindowSelectPreviousTab"; NSString *SPWindowSelectNextTabNotification = @"WindowSelectNextTab"; NSString *SPActivitiesUpdateNotification = @"ActivitiesUpdateNotification"; From 7a202bb467a5330fc2fa498fc33b4ea6872faff9 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 12:27:26 +0100 Subject: [PATCH 17/41] Remove unavailable option --- Interfaces/MainMenu.xib | 6 ------ .../MainViewControllers/SPDatabaseDocument.h | 1 - .../MainViewControllers/SPDatabaseDocument.m | 19 ------------------- Source/Controllers/SPAppController.m | 9 +-------- 4 files changed, 1 insertion(+), 34 deletions(-) diff --git a/Interfaces/MainMenu.xib b/Interfaces/MainMenu.xib index 55cd23820..354b86e0e 100644 --- a/Interfaces/MainMenu.xib +++ b/Interfaces/MainMenu.xib @@ -110,12 +110,6 @@ - - - - - - diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 1b2ad7c05..c14395929 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -295,7 +295,6 @@ - (IBAction)showServerVariables:(id)sender; - (IBAction)showServerProcesses:(id)sender; - (IBAction)shutdownServer:(id)sender; -- (IBAction)openCurrentConnectionInNewWindow:(id)sender; - (IBAction)showGotoDatabase:(id)sender; - (NSArray *)allDatabaseNames; - (NSArray *)allSystemDatabaseNames; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index f017c12a0..987ef04f8 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -2328,13 +2328,6 @@ - (void)flushPrivileges:(id)sender } } -- (IBAction)openCurrentConnectionInNewWindow:(id)sender -{ - [SPAppDelegate newWindow:self]; - SPDatabaseDocument *newTableDocument = [SPAppDelegate frontDocument]; - [newTableDocument setStateFromConnectionFile:[[self fileURL] path]]; -} - /** * Ask the connection controller to initiate connection, if it hasn't * already. Used to support automatic connections on window open, @@ -3205,18 +3198,6 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem ); } - if (action == @selector(openCurrentConnectionInNewWindow:)) - { - if ([self isUntitled]) { - [menuItem setTitle:NSLocalizedString(@"Open in New Window", @"menu item open in new window")]; - return NO; - } - else { - [menuItem setTitle:[NSString stringWithFormat:NSLocalizedString(@"Open “%@” in New Window", @"menu item open “%@” in new window"), [self displayName]]]; - return YES; - } - } - // Data export if (action == @selector(export:)) { return (([self database] != nil) && ([[tablesListInstance tables] count] > 1)); diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index ff9c915cd..7bacdf194 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -517,14 +517,7 @@ - (void)saveConnectionsToSPF:(NSNotification *)notification { /** * Menu item validation. */ -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem -{ - if ([menuItem action] == @selector(openCurrentConnectionInNewWindow:)) - { - [menuItem setTitle:NSLocalizedString(@"Open in New Window", @"menu item open in new window")]; - - return NO; - } +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { if ([menuItem action] == @selector(newTab:)) { return ([[[self.tabManager activeWindowController] window] attachedSheet] == nil); From b2e4c28cdcecb866c33e6d73843f34533455a116 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 12:30:00 +0100 Subject: [PATCH 18/41] Remove invalid check --- Source/Controllers/MainViewControllers/SPDatabaseDocument.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 987ef04f8..1f2ebf70a 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3192,10 +3192,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem } if (!_isConnected || _isWorkingLevel) { - return ( - action == @selector(newWindow:) || - action == @selector(terminate:) - ); + return action == @selector(terminate:); } // Data export From e5e5c9c7b81bfa9a558a0d2bcf1fc89127181404 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 15:33:08 +0100 Subject: [PATCH 19/41] Fix file type --- Resources/Plists/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Plists/Info.plist b/Resources/Plists/Info.plist index 2faa08107..b34e3842e 100644 --- a/Resources/Plists/Info.plist +++ b/Resources/Plists/Info.plist @@ -29,7 +29,7 @@ Owner LSItemContentTypes - com.sequelpro.SequelPro + com.sequelpro.SequelPro.spf com.sequel-ace.sequel-ace.spf NSDocumentClass From 44c246abc0045c6ec9c66d618342d3302617cc71 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:26:16 +0100 Subject: [PATCH 20/41] Add colors as accessory view to tabs --- .../MainViewControllers/SPDatabaseDocument.m | 18 ++++++++++++++++ .../SPDatabaseDocument.swift | 21 +++++++++++++++++++ sequel-ace.xcodeproj/project.pbxproj | 4 ++++ 3 files changed, 43 insertions(+) create mode 100644 Source/Controllers/MainViewControllers/SPDatabaseDocument.swift diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 1f2ebf70a..3cb76eac7 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -109,6 +109,8 @@ @interface SPDatabaseDocument () @property (nonatomic, strong, readwrite) SPWindowController *parentWindowController; @property (assign) BOOL appIsTerminating; +@property (nonatomic, strong) NSView *tabAccessoryView; + - (void)_addDatabase; - (void)_alterDatabase; - (void)_copyDatabase; @@ -346,6 +348,13 @@ - (void)awakeFromNib initComplete = YES; } +- (NSView *)tabAccessoryView { + if (!_tabAccessoryView) { + _tabAccessoryView = [self swiftTabAccessoryView]; + } + return _tabAccessoryView; +} + #pragma mark - /** @@ -3451,6 +3460,15 @@ - (void)updateWindowTitle:(id)sender } [[self.parentWindowController window] setTitle:windowTitle]; + + if (@available(macOS 10.13, *)) { + NSColor *color = [[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]; + NSWindowTab *tab = [[self.parentWindowController window] tab]; + if (tab && color && _isConnected) { + self.tabAccessoryView.layer.backgroundColor = color.CGColor; + tab.accessoryView = self.tabAccessoryView; + } + } } /** diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift b/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift new file mode 100644 index 000000000..145d40abd --- /dev/null +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift @@ -0,0 +1,21 @@ +// +// SPDatabaseDocument.swift +// Sequel Ace +// +// Created by Jakub Kašpar on 11.03.2021. +// Copyright © 2021 Sequel-Ace. All rights reserved. +// + +import AppKit + +extension SPDatabaseDocument { + @objc var swiftTabAccessoryView: NSView { + let view = NSView() + view.wantsLayer = true + view.snp.makeConstraints { + $0.size.equalTo(16) + } + view.layer?.cornerRadius = 8 + return view + } +} diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index d61ad51bc..93655db3c 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -230,6 +230,7 @@ 5132930C25F586A900D803AD /* NotificationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132930925F586A900D803AD /* NotificationToken.swift */; }; 5132930D25F586A900D803AD /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132930A25F586A900D803AD /* TabManager.swift */; }; 513515D2259354BB001E4533 /* NSImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513515D1259354BB001E4533 /* NSImageExtensions.swift */; }; + 514DD98925FACF1500EA3B3B /* SPDatabaseDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514DD98825FACF1500EA3B3B /* SPDatabaseDocument.swift */; }; 515D303F25BD7DE60021CF1E /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = 515D303E25BD7DE60021CF1E /* AppCenterCrashes */; }; 515D304125BD7DE60021CF1E /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 515D304025BD7DE60021CF1E /* AppCenterAnalytics */; }; 517412302573E10C00EB6935 /* SPPrintUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 5174122F2573E10C00EB6935 /* SPPrintUtility.m */; }; @@ -860,6 +861,7 @@ 5132930925F586A900D803AD /* NotificationToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationToken.swift; sourceTree = ""; }; 5132930A25F586A900D803AD /* TabManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = ""; }; 513515D1259354BB001E4533 /* NSImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSImageExtensions.swift; sourceTree = ""; }; + 514DD98825FACF1500EA3B3B /* SPDatabaseDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPDatabaseDocument.swift; sourceTree = ""; }; 5174122E2573E10C00EB6935 /* SPPrintUtility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPPrintUtility.h; sourceTree = ""; }; 5174122F2573E10C00EB6935 /* SPPrintUtility.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPPrintUtility.m; sourceTree = ""; }; 517412372573E8F900EB6935 /* EditorQuickLookTypes.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = EditorQuickLookTypes.plist; sourceTree = ""; }; @@ -1391,6 +1393,7 @@ 17D38F691279E17D00672B13 /* Table Structure */, 17005CB016D6CEA400AF81F4 /* Table Triggers */, 171156501E8B0F40002E6363 /* Table Relations */, + 514DD98825FACF1500EA3B3B /* SPDatabaseDocument.swift */, ); name = "Main View Controllers"; path = MainViewControllers; @@ -3007,6 +3010,7 @@ 1798F1871550175B004B0AB8 /* SPFavoritesExporter.m in Sources */, 1798F1881550175B004B0AB8 /* SPFavoritesImporter.m in Sources */, 1A89556625D6BEED0060CE72 /* GitHubReleaseManager.swift in Sources */, + 514DD98925FACF1500EA3B3B /* SPDatabaseDocument.swift in Sources */, 1798F1951550181B004B0AB8 /* SPGroupNode.m in Sources */, 1798F19815501838004B0AB8 /* SPMutableArrayAdditions.m in Sources */, 1A1EE94A2551185D0056FECD /* DateFormatterExtension.swift in Sources */, From 53560744d3d025d85812eed8825f6adf9380bc40 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:31:41 +0100 Subject: [PATCH 21/41] Update mainToolbar loader --- .../MainViewControllers/SPDatabaseDocument.h | 4 +- .../MainViewControllers/SPDatabaseDocument.m | 80 ++++++++----------- .../Controllers/Other/SPHistoryController.m | 6 +- 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index c14395929..cc1541f2e 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -212,8 +212,7 @@ BOOL taskCanBeCancelled; id taskCancellationCallbackObject; SEL taskCancellationCallbackSelector; - - @public NSToolbar *mainToolbar; + NSToolbarItem *chooseDatabaseToolbarItem; WebView *printWebView; @@ -255,6 +254,7 @@ @property (readwrite) NSStringEncoding sqlFileEncoding; @property (readwrite) BOOL isProcessing; @property (readwrite, copy) NSString *processID; +@property (readonly, nonatomic, strong) NSToolbar *mainToolbar; @property (nonatomic, strong, readonly) SPWindowController *parentWindowController; @property (readonly, strong) SPServerSupport *serverSupport; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 3cb76eac7..25f60f1d8 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -110,6 +110,7 @@ @interface SPDatabaseDocument () @property (assign) BOOL appIsTerminating; @property (nonatomic, strong) NSView *tabAccessoryView; +@property (readwrite, nonatomic, strong) NSToolbar *mainToolbar; - (void)_addDatabase; - (void)_alterDatabase; @@ -206,7 +207,6 @@ - (instancetype)initWithWindowController:(SPWindowController *)windowController allSystemDatabases = nil; gotoDatabaseController = nil; - mainToolbar = nil; isProcessing = NO; printWebView = [[WebView alloc] init]; @@ -258,8 +258,8 @@ - (void)awakeFromNib _mainNibLoaded = YES; - // Set up the toolbar - [self setupToolbar]; + // The history controller needs to track toolbar item state - trigger setup. + [spHistoryControllerInstance setupInterface]; // Set collapsible behaviour on the table list so collapsing behaviour handles resize issus [contentViewSplitter setCollapsibleSubviewIndex:0]; @@ -330,7 +330,7 @@ - (void)awakeFromNib addDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseEncodingButton CollationButton:databaseCollationButton]; // Update the toolbar - [[self.parentWindowController window] setToolbar:mainToolbar]; + [[self.parentWindowController window] setToolbar:self.mainToolbar]; // Update the window's title and represented document [self updateWindowTitle:self]; @@ -348,6 +348,8 @@ - (void)awakeFromNib initComplete = YES; } +#pragma mark - Accessors + - (NSView *)tabAccessoryView { if (!_tabAccessoryView) { _tabAccessoryView = [self swiftTabAccessoryView]; @@ -355,6 +357,16 @@ - (NSView *)tabAccessoryView { return _tabAccessoryView; } +- (NSToolbar *)mainToolbar { + if (!_mainToolbar) { + _mainToolbar = [[NSToolbar alloc] initWithIdentifier:@"TableWindowToolbar"]; + [_mainToolbar setAllowsUserCustomization:YES]; + [_mainToolbar setAutosavesConfiguration:YES]; + [_mainToolbar setDelegate:self]; + } + return _mainToolbar; +} + #pragma mark - /** @@ -1183,7 +1195,7 @@ - (void) startTaskWithDescription:(NSString *)description // Set flags and prevent further UI interaction in this window databaseListIsSelectable = NO; [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskStartNotification object:self]; - [mainToolbar validateVisibleItems]; + [self.mainToolbar validateVisibleItems]; [chooseDatabaseButton setEnabled:NO]; SPLog(@"Schedule appearance of the task window in the near future, using a frame timer"); @@ -1382,7 +1394,7 @@ - (void) endTask // Re-enable window interface databaseListIsSelectable = YES; [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskEndNotification object:self]; - [mainToolbar validateVisibleItems]; + [self.mainToolbar validateVisibleItems]; [chooseDatabaseButton setEnabled:_isConnected]; } } @@ -3417,8 +3429,7 @@ - (NSWindow *)getCreateTableSyntaxWindow /** * Update the window title. */ -- (void)updateWindowTitle:(id)sender -{ +- (void)updateWindowTitle:(id)sender { // Ensure a call on the main thread if (![NSThread isMainThread]) return [[self onMainThread] updateWindowTitle:sender]; @@ -3432,11 +3443,9 @@ - (void)updateWindowTitle:(id)sender if ([connectionController isConnecting]) { windowTitle = [NSMutableString stringWithString:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; - } - else if (!_isConnected) { + } else if (!_isConnected) { windowTitle = [NSMutableString stringWithFormat:@"%@%@", pathName, [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]]; - } - else { + } else { windowTitle = [NSMutableString string]; // Add the path to the window title @@ -3500,31 +3509,12 @@ - (void)clearStatusIcon #pragma mark - #pragma mark Toolbar Methods -/** - * set up the standard toolbar - */ -- (void)setupToolbar -{ - // create a new toolbar instance, and attach it to our document window - mainToolbar = [[NSToolbar alloc] initWithIdentifier:@"TableWindowToolbar"]; - - // set up toolbar properties - [mainToolbar setAllowsUserCustomization:YES]; - [mainToolbar setAutosavesConfiguration:YES]; - - // set ourself as the delegate - [mainToolbar setDelegate:self]; - - // The history controller needs to track toolbar item state - trigger setup. - [spHistoryControllerInstance setupInterface]; -} - /** * Return the identifier for the currently selected toolbar item, or nil if none is selected. */ - (NSString *)selectedToolbarItemIdentifier { - return [mainToolbar selectedItemIdentifier]; + return [self.mainToolbar selectedItemIdentifier]; } /** @@ -4418,7 +4408,7 @@ - (void)restoreSession // Restore toolbar setting if ([spfSession objectForKey:@"isToolbarVisible"]) { - [[mainToolbar onMainThread] setVisible:[[spfSession objectForKey:@"isToolbarVisible"] boolValue]]; + [[self.mainToolbar onMainThread] setVisible:[[spfSession objectForKey:@"isToolbarVisible"] boolValue]]; } // Reset database view encoding if differs from default @@ -5695,12 +5685,12 @@ - (IBAction)viewStructure:(id)sender { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:0]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarTableStructure]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarTableStructure]; [self->spHistoryControllerInstance updateHistoryEntries]; [self->prefs setInteger:SPStructureViewMode forKey:SPLastViewMode]; @@ -5711,12 +5701,12 @@ - (IBAction)viewContent:(id)sender { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:1]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarTableContent]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarTableContent]; [self->spHistoryControllerInstance updateHistoryEntries]; [self->prefs setInteger:SPContentViewMode forKey:SPLastViewMode]; }); @@ -5727,12 +5717,12 @@ - (IBAction)viewQuery:(id)sender { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:2]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarCustomQuery]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarCustomQuery]; [self->spHistoryControllerInstance updateHistoryEntries]; // Set the focus on the text field @@ -5749,12 +5739,12 @@ - (IBAction)viewStatus:(id)sender SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:3]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarTableInfo]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarTableInfo]; [self->spHistoryControllerInstance updateHistoryEntries]; if ([[self table] length]) { @@ -5774,12 +5764,12 @@ - (IBAction)viewRelations:(id)sender SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:4]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarTableRelations]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarTableRelations]; [self->spHistoryControllerInstance updateHistoryEntries]; [self->prefs setInteger:SPRelationsViewMode forKey:SPLastViewMode]; @@ -5793,12 +5783,12 @@ - (IBAction)viewTriggers:(id)sender SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { - [self->mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; + [self.mainToolbar setSelectedItemIdentifier:*SPViewModeToMainToolbarMap[[self->prefs integerForKey:SPLastViewMode]]]; return; } [self->tableTabView selectTabViewItemAtIndex:5]; - [self->mainToolbar setSelectedItemIdentifier:SPMainToolbarTableTriggers]; + [self.mainToolbar setSelectedItemIdentifier:SPMainToolbarTableTriggers]; [self->spHistoryControllerInstance updateHistoryEntries]; [self->prefs setInteger:SPTriggersViewMode forKey:SPLastViewMode]; diff --git a/Source/Controllers/Other/SPHistoryController.m b/Source/Controllers/Other/SPHistoryController.m index 359279222..43fd7f74f 100644 --- a/Source/Controllers/Other/SPHistoryController.m +++ b/Source/Controllers/Other/SPHistoryController.m @@ -66,8 +66,8 @@ - (void)awakeFromNib toolbarItemVisible = NO; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toolbarWillAddItem:) name:NSToolbarWillAddItemNotification object:theDocument->mainToolbar]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toolbarDidRemoveItem:) name:NSToolbarDidRemoveItemNotification object:theDocument->mainToolbar]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toolbarWillAddItem:) name:NSToolbarWillAddItemNotification object:theDocument.mainToolbar]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toolbarDidRemoveItem:) name:NSToolbarDidRemoveItemNotification object:theDocument.mainToolbar]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startDocumentTask:) name:SPDocumentTaskStartNotification object:theDocument]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endDocumentTask:) name:SPDocumentTaskEndNotification object:theDocument]; } @@ -180,7 +180,7 @@ - (IBAction) historyControlClicked:(NSSegmentedControl *)theControl * can cause crashes. */ - (void)setupInterface { - NSArray *toolbarItems = [theDocument->mainToolbar items]; + NSArray *toolbarItems = [theDocument.mainToolbar items]; for (NSToolbarItem *toolbarItem in toolbarItems) { if ([[toolbarItem itemIdentifier] isEqualToString:SPMainToolbarHistoryNavigation]) { From 6292cb148c93a0123711098c39e798464728e04f Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:34:03 +0100 Subject: [PATCH 22/41] Cleanup non-functional code --- Resources/Images/titlebarlock.png | Bin 126 -> 0 bytes .../ConnectionView/SPConnectionController.m | 23 ++++++-------- .../MainViewControllers/SPDatabaseDocument.h | 4 --- .../MainViewControllers/SPDatabaseDocument.m | 29 +----------------- sequel-ace.xcodeproj/project.pbxproj | 4 --- 5 files changed, 11 insertions(+), 49 deletions(-) delete mode 100644 Resources/Images/titlebarlock.png diff --git a/Resources/Images/titlebarlock.png b/Resources/Images/titlebarlock.png deleted file mode 100644 index 697fbc96a9fb76accd5924dde835ef288d5e7795..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)J!3HGPOqkG{NlT9if2N+jzxU@SSJ-A>7qv(PUg Date: Thu, 11 Mar 2021 23:37:48 +0100 Subject: [PATCH 23/41] Remove unused code --- .../ConnectionView/SPConnectionController.m | 9 --------- .../Controllers/MainViewControllers/SPDatabaseDocument.h | 4 ---- 2 files changed, 13 deletions(-) diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 93cd1ef7b..697e02afa 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -1756,7 +1756,6 @@ - (void)_restoreConnectionInterface [progressIndicator display]; [progressIndicatorText setHidden:YES]; [progressIndicatorText display]; - [dbDocument setTitlebarStatus:@""]; // If not testing a connection, Update the password fields, restoring passwords that may have // been bulleted out during connection @@ -2246,8 +2245,6 @@ - (void)initiateSSHTunnelConnection sshTunnel = [[SPSSHTunnel alloc] initToHost:[self sshHost] port:[[self sshPort] integerValue] login:[self sshUser] tunnellingToPort:([[self port] length]?[[self port] integerValue]:3306) onHost:[self host]]; if(sshTunnel == nil) { - [dbDocument setTitlebarStatus:NSLocalizedString(@"SSH Disconnected", @"SSH disconnected titlebar marker")]; - [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"SSH connection failed!", @"SSH connection failed title") errorMessage:@"Failed to Initialize SSH Handle" detail:@"Could not initiate ssh connection worker." @@ -2356,8 +2353,6 @@ - (void)sshTunnelCallback:(SPSSHTunnel *)theTunnel if (newState == SPMySQLProxyIdle) { SPLog(@"SPMySQLProxyIdle, failing"); - [dbDocument setTitlebarStatus:NSLocalizedString(@"SSH Disconnected", @"SSH disconnected titlebar marker")]; - [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"SSH connection failed!", @"SSH connection failed title") errorMessage:[theTunnel lastError] detail:[sshTunnel debugMessages] @@ -2365,13 +2360,9 @@ - (void)sshTunnelCallback:(SPSSHTunnel *)theTunnel } else if (newState == SPMySQLProxyConnected) { SPLog(@"SPMySQLProxyConnected, calling initiateMySQLConnection"); - [dbDocument setTitlebarStatus:NSLocalizedString(@"SSH Connected", @"SSH connected titlebar marker")]; [self initiateMySQLConnection]; } - else { - [dbDocument setTitlebarStatus:NSLocalizedString(@"SSH Connecting…", @"SSH connecting titlebar marker")]; - } } /** diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 69f0cd114..86188b635 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -399,10 +399,6 @@ - (BOOL)isCustomQuerySelected; - (IBAction)showConnectionDebugMessages:(id)sender; -// Titlebar methods -- (void)setTitlebarStatus:(NSString *)status; -- (void)clearStatusIcon; - // Toolbar methods - (void)updateWindowTitle:(id)sender; - (NSString *)selectedToolbarItemIdentifier; From d8e990210569323c8fe3e39f93f298116e4fdd93 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:39:17 +0100 Subject: [PATCH 24/41] Fix styling --- .../ConnectionView/SPConnectionController.m | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 697e02afa..808260cae 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -2331,38 +2331,36 @@ - (void)mySQLConnectionEstablished * state change, allowing connection to fail or proceed as appropriate. If successful, * will call initiateMySQLConnection. */ -- (void)sshTunnelCallback:(SPSSHTunnel *)theTunnel -{ +- (void)sshTunnelCallback:(SPSSHTunnel *)theTunnel { if (cancellingConnection){ SPLog(@"cancellingConnection, returning"); return; } - NSInteger newState = [theTunnel state]; + NSInteger newState = [theTunnel state]; SPLog(@"newState = %li", (long)newState); - // If the user cancelled the password prompt dialog, continue with no further action. - if ([theTunnel passwordPromptCancelled]) { + // If the user cancelled the password prompt dialog, continue with no further action. + if ([theTunnel passwordPromptCancelled]) { SPLog(@"user cancelled the password prompt dialog, continue with no further action"); - [self _restoreConnectionInterface]; + [self _restoreConnectionInterface]; - return; - } + return; + } - if (newState == SPMySQLProxyIdle) { + if (newState == SPMySQLProxyIdle) { SPLog(@"SPMySQLProxyIdle, failing"); - [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"SSH connection failed!", @"SSH connection failed title") - errorMessage:[theTunnel lastError] - detail:[sshTunnel debugMessages] - rawErrorText:[theTunnel lastError]]; - } - else if (newState == SPMySQLProxyConnected) { + [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"SSH connection failed!", @"SSH connection failed title") + errorMessage:[theTunnel lastError] + detail:[sshTunnel debugMessages] + rawErrorText:[theTunnel lastError]]; + } else if (newState == SPMySQLProxyConnected) { SPLog(@"SPMySQLProxyConnected, calling initiateMySQLConnection"); - [self initiateMySQLConnection]; - } + [self initiateMySQLConnection]; + } } /** From e566e0e239b75f5f1fb119eabf8452dcc02bc88b Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:47:04 +0100 Subject: [PATCH 25/41] Move window accessory to window controller to lighten up database document --- .../MainViewControllers/SPDatabaseDocument.m | 32 +++++------------- .../SPDatabaseDocument.swift | 10 +----- .../Window/SPWindowController.swift | 33 ++++++++++++++++++- 3 files changed, 41 insertions(+), 34 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 73a8256b7..9e5df876e 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -109,7 +109,6 @@ @interface SPDatabaseDocument () @property (nonatomic, strong, readwrite) SPWindowController *parentWindowController; @property (assign) BOOL appIsTerminating; -@property (nonatomic, strong) NSView *tabAccessoryView; @property (readwrite, nonatomic, strong) NSToolbar *mainToolbar; - (void)_addDatabase; @@ -350,13 +349,6 @@ - (void)awakeFromNib #pragma mark - Accessors -- (NSView *)tabAccessoryView { - if (!_tabAccessoryView) { - _tabAccessoryView = [self swiftTabAccessoryView]; - } - return _tabAccessoryView; -} - - (NSToolbar *)mainToolbar { if (!_mainToolbar) { _mainToolbar = [[NSToolbar alloc] initWithIdentifier:@"TableWindowToolbar"]; @@ -3431,9 +3423,9 @@ - (NSWindow *)getCreateTableSyntaxWindow */ - (void)updateWindowTitle:(id)sender { // Ensure a call on the main thread - if (![NSThread isMainThread]) return [[self onMainThread] updateWindowTitle:sender]; - - NSMutableString *windowTitle; + if (![NSThread isMainThread]) { + return [[self onMainThread] updateWindowTitle:sender]; + } // Determine name details NSString *pathName = @""; @@ -3442,11 +3434,11 @@ - (void)updateWindowTitle:(id)sender { } if ([connectionController isConnecting]) { - windowTitle = [NSMutableString stringWithString:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]; + [self.parentWindowController updateWindowWithTitle:[NSMutableString stringWithString:NSLocalizedString(@"Connecting…", @"window title string indicating that sp is connecting")]]; } else if (!_isConnected) { - windowTitle = [NSMutableString stringWithFormat:@"%@%@", pathName, [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]]; + [self.parentWindowController updateWindowWithTitle:[NSMutableString stringWithFormat:@"%@%@", pathName, [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]]]; } else { - windowTitle = [NSMutableString string]; + NSMutableString *windowTitle = [NSMutableString string]; // Add the path to the window title [windowTitle appendString:pathName]; @@ -3466,18 +3458,10 @@ - (void)updateWindowTitle:(id)sender { if ([[self table] length]) { [windowTitle appendFormat:@"/%@", [self table]]; } + [self.parentWindowController updateWindowWithTitle:windowTitle]; } - [[self.parentWindowController window] setTitle:windowTitle]; - - if (@available(macOS 10.13, *)) { - NSColor *color = [[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]; - NSWindowTab *tab = [[self.parentWindowController window] tab]; - if (tab && color && _isConnected) { - self.tabAccessoryView.layer.backgroundColor = color.CGColor; - tab.accessoryView = self.tabAccessoryView; - } - } + [self.parentWindowController updateWindowAccessoryWithColor:[[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]]; } #pragma mark - diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift b/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift index 145d40abd..6bb6ec8c2 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.swift @@ -9,13 +9,5 @@ import AppKit extension SPDatabaseDocument { - @objc var swiftTabAccessoryView: NSView { - let view = NSView() - view.wantsLayer = true - view.snp.makeConstraints { - $0.size.equalTo(16) - } - view.layer?.cornerRadius = 8 - return view - } + } diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index cdcf45920..2e6bc70f8 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -45,7 +45,23 @@ import SnapKit setupAppearance() } - private func setupAppearance() { + // MARK: - Accessory + + private lazy var tabAccessoryView: NSView = { + let view = NSView() + view.wantsLayer = true + view.snp.makeConstraints { + $0.size.equalTo(16) + } + view.layer?.cornerRadius = 8 + return view + }() +} + +// MARK: - Private API + +private extension SPWindowController { + func setupAppearance() { databaseDocument.updateWindowTitle(self) window?.contentView?.addSubview(databaseDocument.databaseView()) @@ -53,6 +69,21 @@ import SnapKit } } +// MARK: - Public API + +@objc extension SPWindowController { + func updateWindow(title: String) { + window?.title = title + } + + func updateWindowAccessory(color: NSColor?) { + if #available(macOS 10.13, *) { + tabAccessoryView.layer?.backgroundColor = color?.cgColor + window?.tab.accessoryView = tabAccessoryView + } + } +} + extension SPWindowController: NSWindowDelegate { public func windowShouldClose(_ sender: NSWindow) -> Bool { if !databaseDocument.parentTabShouldClose() { From 6e3b4b38d16360400e339a9e37eabae7f0b0c9b4 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:49:13 +0100 Subject: [PATCH 26/41] Cleanup styling --- .../MainViewControllers/SPDatabaseDocument.m | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 9e5df876e..292eba594 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -364,10 +364,9 @@ - (NSToolbar *)mainToolbar { /** * Set the return code for entering the encryption passowrd sheet */ -- (IBAction)closePasswordSheet:(id)sender -{ +- (IBAction)closePasswordSheet:(id)sender { passwordSheetReturnCode = 0; - if([sender tag]) { + if ([sender tag]) { [NSApp stopModal]; passwordSheetReturnCode = 1; } @@ -380,16 +379,15 @@ - (IBAction)closePasswordSheet:(id)sender - (IBAction)backForwardInHistory:(id)sender { // Ensure history navigation is permitted - trigger end editing and any required saves - if (![self couldCommitCurrentViewActions]) return; + if (![self couldCommitCurrentViewActions]) { + return; + } - switch ([sender tag]) - { - // Go backward - case 0: + switch ([sender tag]) { + case 0: // Go backward [spHistoryControllerInstance goBackInHistory]; break; - // Go forward - case 1: + case 1: // Go forward [spHistoryControllerInstance goForwardInHistory]; break; } From 7496104b5202888b9f80f4c6bae9a22ccef1cb58 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Thu, 11 Mar 2021 23:57:51 +0100 Subject: [PATCH 27/41] Update color only when connected --- Source/Controllers/MainViewControllers/SPDatabaseDocument.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 292eba594..d8faa96fb 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3457,9 +3457,8 @@ - (void)updateWindowTitle:(id)sender { [windowTitle appendFormat:@"/%@", [self table]]; } [self.parentWindowController updateWindowWithTitle:windowTitle]; + [self.parentWindowController updateWindowAccessoryWithColor:[[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]]; } - - [self.parentWindowController updateWindowAccessoryWithColor:[[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]]; } #pragma mark - From e2d478790529e9293a1a426bf86a2934994bc993 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 00:01:23 +0100 Subject: [PATCH 28/41] Use local getter --- Source/Controllers/MainViewControllers/SPDatabaseDocument.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index d8faa96fb..d9f0b8035 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -329,15 +329,15 @@ - (void)awakeFromNib addDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseEncodingButton CollationButton:databaseCollationButton]; // Update the toolbar - [[self.parentWindowController window] setToolbar:self.mainToolbar]; + [self.parentWindowControllerWindow setToolbar:self.mainToolbar]; // Update the window's title and represented document [self updateWindowTitle:self]; - [[self.parentWindowController window] setRepresentedURL:(spfFileURL && [spfFileURL isFileURL] ? spfFileURL : nil)]; + [self.parentWindowControllerWindow setRepresentedURL:(spfFileURL && [spfFileURL isFileURL] ? spfFileURL : nil)]; // Add the progress window to this window [self centerTaskWindow]; - [[self.parentWindowController window] addChildWindow:taskProgressWindow ordered:NSWindowAbove]; + [self.parentWindowControllerWindow addChildWindow:taskProgressWindow ordered:NSWindowAbove]; // If not connected, update the favorite selection if (!_isConnected) { From 9c728f0b28d0b6459dafb892a2a19e7d001f4241 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 14:22:41 +0100 Subject: [PATCH 29/41] Show lock if connection is SSL --- .../FallbackIcons/Contents.json | 6 ++++ .../fallback_lock.fill.imageset/Contents.json | 15 +++++++++ .../fallback_lock.fill.imageset/lock.fill.pdf | Bin 0 -> 2845 bytes .../ConnectionView/SPConnectionController.h | 1 + .../ConnectionView/SPConnectionController.m | 7 ++-- .../MainViewControllers/SPDatabaseDocument.m | 2 +- .../Window/SPWindowController.swift | 31 ++++++++++++++---- 7 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 Resources/Images.xcassets/FallbackIcons/Contents.json create mode 100644 Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/Contents.json create mode 100644 Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/lock.fill.pdf diff --git a/Resources/Images.xcassets/FallbackIcons/Contents.json b/Resources/Images.xcassets/FallbackIcons/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Resources/Images.xcassets/FallbackIcons/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/Contents.json b/Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/Contents.json new file mode 100644 index 000000000..d9ccd990f --- /dev/null +++ b/Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "lock.fill.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/lock.fill.pdf b/Resources/Images.xcassets/FallbackIcons/fallback_lock.fill.imageset/lock.fill.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9cdeeaf4396bde3d7b4e5d44a6a2bc494dfe199b GIT binary patch literal 2845 zcmb_eU5pb|6b1!Nsvv5N5+1mzBD;aaiG^0o{CVcr5D#czk8TMi5^z1TO5PaYuq6)_!}O2?6;t()j5J$E z$z;g&9Hf>*{<)ENPLvlg_sZ_bsnFP!m3tmKHgD?7U6)_`_Qy-h>FSb&kL(*e@a(|! zjvYIz{Ygt zvE?8>aQwyh&rNSQ4_?1-zxHPO{-yWKzB2gUsc*JV&2FDrJbq-+_G>4+BYS^3{Mpr) z{`&1e`QsOq;^|8l&hFg(;jTOHSi|ksugzYWKK{1&Jd?PXn0o6|{>=GLj!vBXT^9~5 z{rmH6BmeAQ_3F|7>66Ax2w8fa0=y!u5w6HD%g4z_vW&I}&G_Ehf`dWx#)qTUc3z*Kv-19}R`F^V8nEE<;KO#m6WM#(}BU?O6K!H&a* zXClyJ+S=Ag(J;+OMK3nu4cn6O{-8&eSej*Mj$s*|jxy{jnpsKHE3seJ)^FyLb8Nk; z;VpY`?U=^ss+>Fs#0VRqD*|PJO+95*8!Bw-?G3e#M$THVtKo?Xf=w>qP!0rVgm$IA z7|LY<(+Xv~LUU>f!JO(K%L5Fd5DwUuhu>U4sy7ew$hE7EhFn0%&%-Rz4K;218)^K? z@_^$bbbNDb0|L^X8`;3cpjEN~e9F+>jesPPZ;KIIG4(!)6Au_1E{i->S3MOLs-qq` z?Q_}nc)NP7B>Me|s%=Fc7)2$+>I+{!@m&}gdS7^hkfpPg0W@Z;n{-fN^66o1a;qll z;r?U@;3wfrez{V{=)f+bKat6h%n0kYy?CLAeu_r}~uTKH9{oBjGC39HZjl0s;hC9kr`oUpU;zqg=^m zn;TeeB*-eF*=6Xf705(rST47ctDS|!NQ0K^sg{NY zDLSL@R7#AdWm?W~vY;d&W}!1SpohQ`l7f%2tyRmoC>p?uBBV2Eo~P0R2IkW76eXnC zG$qoa%*Oecl2L>Pa9eB>I04DI+jwX&eaj5pn4dPrYiE#xjz^>!lcZTGnxhzYnBgTl zDg_-Y(R7e;yJs`sItXrOqd0LZAZ?!AAobZZY};n?hU2F#9oq@qyP+DbaZ4H1+bHmD z0{zcF0#C!a{|Nj67b@3PrPwMp=3R2maaWsmy$RUidK=TlOf{<`Ew`iOLg@~ z27@)otYy1hndw?HuS(T1gL$HB5SfUyor_ary13Le$s^*_>YSioNnfQ*uhUxZD$^hn zMlw~a)ED+C9TnB8>4lRW>Q<`=)96H~S-XG}@cJbFv!H4p@DQy5Vnqj5LR}sXT16X>s}f$y8xxAarWipsW>yFW{HuWB4|_A~U3f{ss6_RYCv& literal 0 HcmV?d00001 diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h index f74e4f8f7..e260eb14f 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h @@ -262,6 +262,7 @@ typedef NS_ENUM(NSInteger, SPConnectionTimeZoneMode) { -(BOOL)validateKeyFile:(NSURL *)url error:(NSError **)outError; -(void)showValidationAlertForError:(NSError*)err; -(BOOL)connected; +- (BOOL)isConnectedViaSSL; // Favorites interaction - (void)updateFavoriteSelection:(id)sender; diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 808260cae..583fc9e77 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -363,6 +363,10 @@ - (IBAction)cancelConnection:(id)sender [self _restoreConnectionInterface]; } +- (BOOL)isConnectedViaSSL { + return [mySQLConnection isConnectedViaSSL]; +} + #pragma mark - #pragma mark Interface interaction @@ -2319,9 +2323,6 @@ - (void)mySQLConnectionEstablished [favoritesOutlineView setEnabled:YES]; [favoritesOutlineView display]; - // Release the tunnel if set - will now be retained by the connection - - // Pass the connection to the document and clean up the interface [self addConnectionToDocument]; } diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index d9f0b8035..7d0bef093 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3457,7 +3457,7 @@ - (void)updateWindowTitle:(id)sender { [windowTitle appendFormat:@"/%@", [self table]]; } [self.parentWindowController updateWindowWithTitle:windowTitle]; - [self.parentWindowController updateWindowAccessoryWithColor:[[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]]; + [self.parentWindowController updateWindowAccessoryWithColor:[[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]] isSSL:[self.connectionController isConnectedViaSSL]]; } } diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index 2e6bc70f8..1801bf84a 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -51,11 +51,21 @@ import SnapKit let view = NSView() view.wantsLayer = true view.snp.makeConstraints { - $0.size.equalTo(16) + $0.size.equalTo(20) } - view.layer?.cornerRadius = 8 + view.layer?.cornerRadius = 10 return view }() + + private lazy var tabAccessoryViewImage: NSImageView = { + var image = NSImage(imageLiteralResourceName: "fallback_lock.fill") + if #available(macOS 11, *), let systemImage = NSImage(systemSymbolName: "lock.fill", accessibilityDescription: nil) { + image = systemImage + } + let imageView = NSImageView(image: image) + imageView.isHidden = true + return imageView + }() } // MARK: - Private API @@ -66,6 +76,15 @@ private extension SPWindowController { window?.contentView?.addSubview(databaseDocument.databaseView()) databaseDocument.databaseView()?.frame = window?.contentView?.frame ?? NSRect(x: 0, y: 0, width: 800, height: 400) + + tabAccessoryView.addSubview(tabAccessoryViewImage) + tabAccessoryViewImage.snp.makeConstraints { + $0.edges.equalToSuperview() + } + + if #available(macOS 10.13, *) { + window?.tab.accessoryView = tabAccessoryView + } } } @@ -76,11 +95,9 @@ private extension SPWindowController { window?.title = title } - func updateWindowAccessory(color: NSColor?) { - if #available(macOS 10.13, *) { - tabAccessoryView.layer?.backgroundColor = color?.cgColor - window?.tab.accessoryView = tabAccessoryView - } + func updateWindowAccessory(color: NSColor?, isSSL: Bool) { + tabAccessoryView.layer?.backgroundColor = color?.cgColor + tabAccessoryViewImage.isHidden = !isSSL } } From bdfe10e6b1b878914c9ac36fa1ffb06f33e5a1a9 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 14:39:23 +0100 Subject: [PATCH 30/41] Add tooltip for mouse hover --- Source/Controllers/Window/SPWindowController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Controllers/Window/SPWindowController.swift b/Source/Controllers/Window/SPWindowController.swift index 1801bf84a..41531f04f 100644 --- a/Source/Controllers/Window/SPWindowController.swift +++ b/Source/Controllers/Window/SPWindowController.swift @@ -63,6 +63,7 @@ import SnapKit image = systemImage } let imageView = NSImageView(image: image) + imageView.toolTip = NSLocalizedString("SSH Connected", comment: "Tooltip information text") imageView.isHidden = true return imageView }() From f3bc43a2a9da90173f17dc5c233ad9227d042ced Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 22:07:56 +0100 Subject: [PATCH 31/41] Fix resizing connection view when opening new tab, fix all sizing weirdness --- Interfaces/ConnectionView.xib | 11 +-- Interfaces/DBView.xib | 90 +++++++++---------- .../ConnectionView/SPConnectionController.m | 26 ++---- .../MainViewControllers/SPDatabaseDocument.m | 8 -- Source/Controllers/SPAppController.m | 18 ++-- 5 files changed, 67 insertions(+), 86 deletions(-) diff --git a/Interfaces/ConnectionView.xib b/Interfaces/ConnectionView.xib index 1aeb152da..d0b3cabd4 100644 --- a/Interfaces/ConnectionView.xib +++ b/Interfaces/ConnectionView.xib @@ -71,7 +71,7 @@ - + @@ -250,10 +250,10 @@ - + - + @@ -1789,7 +1789,7 @@ DQ - + @@ -1799,7 +1799,7 @@ DQ - + @@ -2772,6 +2772,7 @@ DQ + diff --git a/Interfaces/DBView.xib b/Interfaces/DBView.xib index 4c9accae6..1cad92584 100644 --- a/Interfaces/DBView.xib +++ b/Interfaces/DBView.xib @@ -1748,15 +1748,15 @@ Gw - + - + - + @@ -1765,12 +1765,12 @@ Gw - + - + @@ -1792,17 +1792,17 @@ Gw - + - + - + @@ -1811,12 +1811,12 @@ Gw - + - + @@ -1837,7 +1837,7 @@ Gw - + @@ -1849,7 +1849,7 @@ Gw - + @@ -1858,7 +1858,7 @@ Gw - + @@ -1867,7 +1867,7 @@ Gw - + @@ -1876,7 +1876,7 @@ Gw - + @@ -1885,7 +1885,7 @@ Gw - + @@ -1894,7 +1894,7 @@ Gw - + @@ -1906,7 +1906,7 @@ Gw - + @@ -1918,7 +1918,7 @@ Gw - + @@ -1930,16 +1930,16 @@ Gw - + - + - - + + @@ -1947,8 +1947,8 @@ Gw - - + + @@ -1956,8 +1956,8 @@ Gw - - + + @@ -1965,7 +1965,7 @@ Gw - + @@ -1978,8 +1978,8 @@ Gw - - + + @@ -1987,8 +1987,8 @@ Gw - - + + @@ -1996,7 +1996,7 @@ Gw - + @@ -2005,7 +2005,7 @@ Gw - + @@ -2014,7 +2014,7 @@ Gw - + @@ -2037,7 +2037,7 @@ Gw - + @@ -2046,7 +2046,7 @@ Gw - + @@ -2055,7 +2055,7 @@ Gw - + @@ -2064,7 +2064,7 @@ Gw - + @@ -2073,7 +2073,7 @@ Gw - + @@ -2082,7 +2082,7 @@ Gw - + @@ -2091,7 +2091,7 @@ Gw - + @@ -2100,7 +2100,7 @@ Gw - + @@ -2109,7 +2109,7 @@ Gw - + @@ -2118,7 +2118,7 @@ Gw - + diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 583fc9e77..93265c25b 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -736,13 +736,13 @@ - (IBAction)updateKeyLocationFileVisibility:(id)sender */ - (void)updateSplitViewSize { - if ([dbDocument getConnection]) { - return; - } - - [connectionSplitView setDelegate:nil]; - [connectionSplitView setPosition:[[[databaseConnectionView subviews] firstObject] frame].size.width ofDividerAtIndex:0]; - [connectionSplitView setDelegate:self]; +// if ([dbDocument getConnection]) { +// return; +// } +// +// [connectionSplitView setDelegate:nil]; +// [connectionSplitView setPosition:[[[databaseConnectionView subviews] firstObject] frame].size.width ofDividerAtIndex:0]; +// [connectionSplitView setDelegate:self]; } - (IBAction)updateClearTextPlugin:(id)sender @@ -2486,18 +2486,6 @@ - (void)_showConnectionTestResult:(NSString *)resultString #pragma mark SplitView delegate methods -/** - * When the split view is resized, trigger a resize in the hidden table - * width as well, to keep the connection view and connected view in sync. - */ -- (void)splitViewDidResizeSubviews:(NSNotification *)notification -{ - if (initComplete) { - allowSplitViewResizing = YES; - [databaseConnectionView setPosition:[[[connectionSplitView subviews] objectAtIndex:0] frame].size.width ofDividerAtIndex:0]; - } -} - - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex { return 145.f; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 7d0bef093..44e5d8029 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -5089,14 +5089,6 @@ - (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRec #pragma mark - #pragma mark SplitView delegate methods -- (void)splitViewDidResizeSubviews:(NSNotification *)notification -{ - if (initComplete) { - allowSplitViewResizing = YES; - [connectionController updateSplitViewSize]; - } -} - - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex { if (dividerIndex == 0 && proposedMinimumPosition < 40) { diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 7bacdf194..a2b085e16 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -265,15 +265,15 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { } } } - executeOnBackgroundThread(^{ - NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; - - // fake the dbViewInfoPanelSplit being open - NSMutableArray *dbViewInfoPanelSplit = [[NSMutableArray alloc] initWithCapacity:2]; - [dbViewInfoPanelSplit addObject:@"0.000000, 0.000000, 359.500000, 577.500000, NO, NO"]; - [dbViewInfoPanelSplit addObject:@"0.000000, 586.500000, 359.500000, 190.500000, NO, NO"]; - [prefs setObject:dbViewInfoPanelSplit forKey:@"NSSplitView Subview Frames DbViewInfoPanelSplit"]; - }); +// executeOnBackgroundThread(^{ +// NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; +// +// // fake the dbViewInfoPanelSplit being open +// NSMutableArray *dbViewInfoPanelSplit = [[NSMutableArray alloc] initWithCapacity:2]; +// [dbViewInfoPanelSplit addObject:@"0.000000, 0.000000, 359.500000, 577.500000, NO, NO"]; +// [dbViewInfoPanelSplit addObject:@"0.000000, 586.500000, 359.500000, 190.500000, NO, NO"]; +// [prefs setObject:dbViewInfoPanelSplit forKey:@"NSSplitView Subview Frames DbViewInfoPanelSplit"]; +// }); [self checkForNewVersionWithDelay:SPDelayBeforeCheckingForNewReleases andIsFromMenuCheck:NO]; From 89192107b05a5beecdd197807e2171d40fdaf50f Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 22:09:22 +0100 Subject: [PATCH 32/41] Revert comment out --- Source/Controllers/SPAppController.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index a2b085e16..7bacdf194 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -265,15 +265,15 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { } } } -// executeOnBackgroundThread(^{ -// NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; -// -// // fake the dbViewInfoPanelSplit being open -// NSMutableArray *dbViewInfoPanelSplit = [[NSMutableArray alloc] initWithCapacity:2]; -// [dbViewInfoPanelSplit addObject:@"0.000000, 0.000000, 359.500000, 577.500000, NO, NO"]; -// [dbViewInfoPanelSplit addObject:@"0.000000, 586.500000, 359.500000, 190.500000, NO, NO"]; -// [prefs setObject:dbViewInfoPanelSplit forKey:@"NSSplitView Subview Frames DbViewInfoPanelSplit"]; -// }); + executeOnBackgroundThread(^{ + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + + // fake the dbViewInfoPanelSplit being open + NSMutableArray *dbViewInfoPanelSplit = [[NSMutableArray alloc] initWithCapacity:2]; + [dbViewInfoPanelSplit addObject:@"0.000000, 0.000000, 359.500000, 577.500000, NO, NO"]; + [dbViewInfoPanelSplit addObject:@"0.000000, 586.500000, 359.500000, 190.500000, NO, NO"]; + [prefs setObject:dbViewInfoPanelSplit forKey:@"NSSplitView Subview Frames DbViewInfoPanelSplit"]; + }); [self checkForNewVersionWithDelay:SPDelayBeforeCheckingForNewReleases andIsFromMenuCheck:NO]; From 180801dddd51c69082ae7bf89a7c1f319f1d364d Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 23:12:11 +0100 Subject: [PATCH 33/41] Start reworking menu actions and responder chain --- Interfaces/DBView.xib | 11 +++--- .../DataExport/SPExportController.h | 2 +- .../DataExport/SPExportController.m | 5 +-- .../MainViewControllers/SPDatabaseDocument.h | 11 ++++-- .../MainViewControllers/SPDatabaseDocument.m | 22 +++++------ Source/Controllers/SPAppController.h | 4 +- Source/Controllers/SPAppController.m | 39 +++++-------------- Source/Controllers/SPAppController.swift | 28 ++++++++++++- sequel-ace.xcodeproj/project.pbxproj | 2 +- 9 files changed, 67 insertions(+), 57 deletions(-) diff --git a/Interfaces/DBView.xib b/Interfaces/DBView.xib index 1cad92584..3e973c504 100644 --- a/Interfaces/DBView.xib +++ b/Interfaces/DBView.xib @@ -1939,7 +1939,7 @@ Gw - + @@ -1948,7 +1948,7 @@ Gw - + @@ -1957,7 +1957,7 @@ Gw - + @@ -1979,7 +1979,7 @@ Gw - + @@ -1988,7 +1988,7 @@ Gw - + @@ -4704,6 +4704,7 @@ Gw + diff --git a/Source/Controllers/DataExport/SPExportController.h b/Source/Controllers/DataExport/SPExportController.h index c1c961f7d..a23365571 100644 --- a/Source/Controllers/DataExport/SPExportController.h +++ b/Source/Controllers/DataExport/SPExportController.h @@ -274,7 +274,7 @@ - (BOOL)setExportInput:(SPExportSource)input; // IB action methods -- (IBAction)export:(id)sender; +- (void)exportData; - (IBAction)closeSheet:(id)sender; - (IBAction)switchInput:(id)sender; - (IBAction)cancelExport:(id)sender; diff --git a/Source/Controllers/DataExport/SPExportController.m b/Source/Controllers/DataExport/SPExportController.m index f93954953..79ad50a49 100644 --- a/Source/Controllers/DataExport/SPExportController.m +++ b/Source/Controllers/DataExport/SPExportController.m @@ -398,8 +398,7 @@ - (void)displayExportFinishedNotification * * @param sender The caller (can be anything or nil as it is not currently used). */ -- (IBAction)export:(id)sender -{ +- (void)exportData { SPExportType selectedExportType = SPAnyExportType; SPExportSource selectedExportSource = SPTableExport; @@ -1076,7 +1075,7 @@ - (void)_checkForDatabaseChanges [self performSelector:@selector(initializeExportUsingSelectedOptions) withObject:nil afterDelay:0.5]; } cancelButtonHandler:^{ // Cancel the export and redisplay the export dialog after a short delay - [self performSelector:@selector(export:) withObject:self afterDelay:0.5]; + [self performSelector:@selector(exportData) withObject:self afterDelay:0.5]; }]; } else { diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 86188b635..93c754b12 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -336,7 +336,6 @@ - (IBAction)copyCreateTableSyntaxFromSheet:(id)sender; - (IBAction)focusOnTableContentFilter:(id)sender; - (IBAction)showFilterTable:(id)sender; -- (IBAction)export:(id)sender; - (IBAction)exportSelectedTablesAs:(id)sender; - (IBAction)multipleLineEditingButtonClicked:(NSButton *)sender; @@ -393,9 +392,6 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem; - (IBAction)openDatabaseInNewTab:(id)sender; - (IBAction)saveConnectionSheet:(id)sender; -- (IBAction)import:(id)sender; -- (IBAction)importFromClipboard:(id)sender; -- (IBAction)addConnectionToFavorites:(id)sender; - (BOOL)isCustomQuerySelected; - (IBAction)showConnectionDebugMessages:(id)sender; @@ -429,6 +425,13 @@ - (SPConnectionController*)connectionController; +#pragma mark - Menu actions called from SPAppController + +- (void)exportData; +- (void)addConnectionToFavorites; +- (void)importFile; +- (void)importFromClipboard; + #pragma mark - SPDatabaseViewController // Accessors diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 44e5d8029..eec16ffae 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -2237,9 +2237,10 @@ - (IBAction)exportSelectedTablesAs:(id)sender /** * Opens the data export dialog. */ -- (IBAction)export:(id)sender -{ - [exportControllerInstance export:self]; +- (void)exportData { + if (_isConnected) { + [exportControllerInstance exportData]; + } } #pragma mark - @@ -3144,16 +3145,14 @@ - (IBAction)openDatabaseInNewTab:(id)sender { /** * Passes the request to the dataImport object */ -- (IBAction)import:(id)sender -{ +- (void)importFile { [tableDumpInstance importFile]; } /** * Passes the request to the dataImport object */ -- (IBAction)importFromClipboard:(id)sender -{ +- (void)importFromClipboard { [tableDumpInstance importFromClipboard]; } @@ -3375,7 +3374,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem // If validation for the sort favorites tableview items reaches here then the preferences window isn't // open return NO. - if ((action == @selector(sortFavorites:)) || ([menuItem action] == @selector(reverseSortFavorites:))) { + if ((action == @selector(sortFavorites:)) || (action == @selector(reverseSortFavorites:))) { return NO; } @@ -3386,12 +3385,13 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem /** * Adds the current database connection details to the user's favorites if it doesn't already exist. */ -- (IBAction)addConnectionToFavorites:(id)sender -{ +- (void)addConnectionToFavorites { // Obviously don't add if it already exists. We shouldn't really need this as the menu item validation // enables or disables the menu item based on the same method. Although to be safe do the check anyway // as we don't know what's calling this method. - if ([connectionController selectedFavorite] && ![connectionController isEditingConnection]) return; + if ([connectionController selectedFavorite] && ![connectionController isEditingConnection]) { + return; + } // Request the connection controller to add its details to favorites [connectionController addFavoriteUsingCurrentDetails:self]; diff --git a/Source/Controllers/SPAppController.h b/Source/Controllers/SPAppController.h index 992aae069..67820e501 100755 --- a/Source/Controllers/SPAppController.h +++ b/Source/Controllers/SPAppController.h @@ -38,6 +38,7 @@ @class SPBundleEditorController; @class SPWindowController; @class HyperlinkTextField; +@class TabManager; @interface SPAppController : NSObject { @@ -56,6 +57,7 @@ @property (readwrite, copy) NSString *lastBundleBlobFilesDirectory; @property (nonatomic, strong) NSMutableArray *sshProcessIDs; +@property (nonatomic, strong, readonly) TabManager *tabManager; @property (weak) IBOutlet NSView *staleBookmarkHelpView; @property (weak) IBOutlet HyperlinkTextField *staleBookmarkTextField; @@ -110,8 +112,6 @@ #pragma mark - SPWindowManagement -- (IBAction)newWindow:(id)sender; -- (IBAction)newTab:(id)sender; - (IBAction)duplicateTab:(id)sender; @end diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index 7bacdf194..c0bc44ac0 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -78,7 +78,7 @@ - (void)checkForNewVersionFromMenu; @property (readwrite, strong) NSFileManager *fileManager; @property (readwrite, strong) SPBundleManager *sharedSPBundleManager; -@property (nonatomic, strong) TabManager *tabManager; +@property (nonatomic, strong, readwrite) TabManager *tabManager; @end @@ -518,16 +518,20 @@ - (void)saveConnectionsToSPF:(NSNotification *)notification { * Menu item validation. */ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { - - if ([menuItem action] == @selector(newTab:)) { + SEL action = [menuItem action]; + if (action == @selector(newWindow:) || action == @selector(openConnectionSheet:)) { + return YES; + } + if (action == @selector(newTab:)) { return ([[[self.tabManager activeWindowController] window] attachedSheet] == nil); } - - if ([menuItem action] == @selector(duplicateTab:)) - { + if (action == @selector(duplicateTab:)) { return ([[self frontDocument] getConnection] != nil); } + if (self.tabManager.activeWindowController.databaseDocument) { + return [self.tabManager.activeWindowController.databaseDocument validateMenuItem:menuItem]; + } return YES; } @@ -1339,18 +1343,6 @@ - (IBAction)openPreferences:(id)sender [prefsController showWindow:self]; } -- (IBAction)import:(id)sender { - [[[self.tabManager activeWindowController] databaseDocument] import:sender]; -} - -- (IBAction)importFromClipboard:(id)sender { - [[[self.tabManager activeWindowController] databaseDocument] importFromClipboard:sender]; -} - -- (IBAction)saveConnectionSheet:(id)sender { - [[[self.tabManager activeWindowController] databaseDocument] saveConnectionSheet:sender]; -} - #pragma mark - #pragma mark Accessors @@ -1654,17 +1646,6 @@ - (IBAction)newWindowForTab:(id)sender { [self.tabManager newWindowForTab]; } -- (IBAction)newWindow:(id)sender { - [self.tabManager newWindowForWindow]; -} - -/** - * Create a new tab in the frontmost window. - */ -- (IBAction)newTab:(id)sender { - [self.tabManager newWindowForTab]; -} - /** * Duplicate the current connection tab */ diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index dbefe4e98..7b289a5af 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -9,5 +9,31 @@ import AppKit extension SPAppController { - + @IBAction func newWindow(_ sender: Any) { + tabManager.newWindowForWindow() + } + + @IBAction func newTab(_ sender: Any) { + tabManager.newWindowForTab() + } + + @IBAction func export(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.exportData() + } + + @IBAction func addConnectionToFavorites(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.addConnectionToFavorites() + } + + @IBAction func saveConnectionSheet(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.saveConnectionSheet(sender) + } + + @IBAction func `import`(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.importFile() + } + + @IBAction func importFromClipboard(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.importFromClipboard() + } } diff --git a/sequel-ace.xcodeproj/project.pbxproj b/sequel-ace.xcodeproj/project.pbxproj index 8555b3a8f..49bfda2be 100644 --- a/sequel-ace.xcodeproj/project.pbxproj +++ b/sequel-ace.xcodeproj/project.pbxproj @@ -1787,9 +1787,9 @@ 17D390A6127B54F300672B13 /* Preferences */, 17E6414A0EF01EF6001BC333 /* SPAppController.h */, 17E6414B0EF01EF6001BC333 /* SPAppController.m */, + 51BB391B25F82B060048CA69 /* SPAppController.swift */, 173E70D2107FF687008733C9 /* Subview Controllers */, 17D3583C1533766800A654D7 /* Window */, - 51BB391B25F82B060048CA69 /* SPAppController.swift */, ); path = Controllers; sourceTree = ""; From f6daa6f277f928a7335d6e46334998706fb76a3b Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Fri, 12 Mar 2021 23:45:36 +0100 Subject: [PATCH 34/41] Rework File and partially View menu --- Interfaces/DBView.xib | 42 +++--- Interfaces/MainMenu.xib | 11 -- .../MainViewControllers/SPDatabaseDocument.h | 22 ++-- .../MainViewControllers/SPDatabaseDocument.m | 123 +++++++++--------- .../Controllers/Other/SPHistoryController.m | 12 +- Source/Controllers/SPAppController.swift | 37 ++++++ .../SubviewControllers/SPTablesList.m | 2 +- 7 files changed, 140 insertions(+), 109 deletions(-) diff --git a/Interfaces/DBView.xib b/Interfaces/DBView.xib index 3e973c504..06d6415e6 100644 --- a/Interfaces/DBView.xib +++ b/Interfaces/DBView.xib @@ -399,26 +399,26 @@ - + - + - + - + - + - + @@ -612,7 +612,7 @@ - + @@ -623,7 +623,7 @@ - + @@ -751,18 +751,18 @@ - + - + - + - + @@ -894,7 +894,7 @@ - + @@ -937,7 +937,7 @@ - + @@ -950,7 +950,7 @@ - + @@ -1939,7 +1939,7 @@ Gw - + @@ -1948,7 +1948,7 @@ Gw - + @@ -1957,7 +1957,7 @@ Gw - + @@ -1979,7 +1979,7 @@ Gw - + @@ -1988,7 +1988,7 @@ Gw - + diff --git a/Interfaces/MainMenu.xib b/Interfaces/MainMenu.xib index 354b86e0e..5db884c72 100644 --- a/Interfaces/MainMenu.xib +++ b/Interfaces/MainMenu.xib @@ -184,20 +184,9 @@ - - - - - - - diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 93c754b12..8a76a499c 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -344,7 +344,6 @@ - (IBAction)closePanelSheet:(id)sender; - (IBAction)validateSaveConnectionAccessory:(id)sender; - (IBAction)closePasswordSheet:(id)sender; -- (IBAction)backForwardInHistory:(id)sender; - (IBAction)showUserManager:(id)sender; - (IBAction)copyChecksumFromSheet:(id)sender; - (IBAction)showNavigator:(id)sender; @@ -427,10 +426,23 @@ #pragma mark - Menu actions called from SPAppController +#pragma mark File menu + - (void)exportData; - (void)addConnectionToFavorites; - (void)importFile; - (void)importFromClipboard; +- (void)printDocument; + +#pragma mark View menu + +- (void)viewStructure; +- (void)viewContent; +- (void)viewQuery; +- (void)viewStatus; +- (void)viewRelations; +- (void)viewTriggers; +- (void)backForwardInHistory:(id)sender; #pragma mark - SPDatabaseViewController @@ -442,14 +454,6 @@ - (BOOL)contentLoaded; - (BOOL)statusLoaded; -// Tab view control -- (IBAction)viewStructure:(id)sender; -- (IBAction)viewContent:(id)sender; -- (IBAction)viewQuery:(id)sender; -- (IBAction)viewStatus:(id)sender; -- (IBAction)viewRelations:(id)sender; -- (IBAction)viewTriggers:(id)sender; - - (void)setStructureRequiresReload:(BOOL)reload; - (void)setContentRequiresReload:(BOOL)reload; - (void)setStatusRequiresReload:(BOOL)reload; diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index eec16ffae..2744deb1a 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -257,6 +257,9 @@ - (void)awakeFromNib _mainNibLoaded = YES; + // Update the toolbar + [self.parentWindowControllerWindow setToolbar:self.mainToolbar]; + // The history controller needs to track toolbar item state - trigger setup. [spHistoryControllerInstance setupInterface]; @@ -328,9 +331,6 @@ - (void)awakeFromNib alterDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseAlterEncodingButton CollationButton:databaseAlterCollationButton]; addDatabaseCharsetHelper = [[SPCharsetCollationHelper alloc] initWithCharsetButton:databaseEncodingButton CollationButton:databaseCollationButton]; - // Update the toolbar - [self.parentWindowControllerWindow setToolbar:self.mainToolbar]; - // Update the window's title and represented document [self updateWindowTitle:self]; [self.parentWindowControllerWindow setRepresentedURL:(spfFileURL && [spfFileURL isFileURL] ? spfFileURL : nil)]; @@ -376,8 +376,7 @@ - (IBAction)closePasswordSheet:(id)sender { /** * Go backward or forward in the history depending on the menu item selected. */ -- (IBAction)backForwardInHistory:(id)sender -{ +- (void)backForwardInHistory:(id)sender { // Ensure history navigation is permitted - trigger end editing and any required saves if (![self couldCommitCurrentViewActions]) { return; @@ -517,7 +516,7 @@ - (void)setConnection:(SPMySQLConnection *)theConnection // Insert queryEditorInitString into the Query Editor if defined if (queryEditorInitString && [queryEditorInitString length]) { - [self viewQuery:self]; + [self viewQuery]; [customQueryInstance doPerformLoadQueryService:queryEditorInitString]; } @@ -537,22 +536,22 @@ - (void)setConnection:(SPMySQLConnection *)theConnection switch ([prefs integerForKey:SPDefaultViewMode] > 0 ? [prefs integerForKey:SPDefaultViewMode] : [prefs integerForKey:SPLastViewMode]) { default: case SPStructureViewMode: - [self viewStructure:self]; + [self viewStructure]; break; case SPContentViewMode: - [self viewContent:self]; + [self viewContent]; break; case SPRelationsViewMode: - [self viewRelations:self]; + [self viewRelations]; break; case SPTableInfoViewMode: - [self viewStatus:self]; + [self viewStatus]; break; case SPQueryEditorViewMode: - [self viewQuery:self]; + [self viewQuery]; break; case SPTriggersViewMode: - [self viewTriggers:self]; + [self viewTriggers]; break; } } @@ -2202,7 +2201,7 @@ - (IBAction)copyCreateTableSyntaxFromSheet:(id)sender */ - (IBAction)focusOnTableContentFilter:(id)sender { - [self viewContent:self]; + [self viewContent]; [tableContentInstance performSelector:@selector(makeContentFilterHaveFocus) withObject:nil afterDelay:0.1]; } @@ -2212,7 +2211,7 @@ - (IBAction)focusOnTableContentFilter:(id)sender */ - (IBAction)showFilterTable:(id)sender { - [self viewContent:self]; + [self viewContent]; [tableContentInstance performSelector:@selector(showFilterTable:) withObject:sender afterDelay:0.1]; } @@ -2308,19 +2307,17 @@ - (IBAction)showUserManager:(id)sender /** * Passes query to tablesListInstance */ -- (void)doPerformQueryService:(NSString *)query -{ +- (void)doPerformQueryService:(NSString *)query { [[self.parentWindowController window] makeKeyAndOrderFront:self]; - [self viewQuery:nil]; + [self viewQuery]; [customQueryInstance doPerformQueryService:query]; } /** * Inserts query into the Custom Query editor */ -- (void)doPerformLoadQueryService:(NSString *)query -{ - [self viewQuery:nil]; +- (void)doPerformLoadQueryService:(NSString *)query { + [self viewQuery]; [customQueryInstance doPerformLoadQueryService:query]; } @@ -3244,11 +3241,11 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem } // Table specific actions - if (action == @selector(viewStructure:) || - action == @selector(viewContent:) || - action == @selector(viewRelations:) || - action == @selector(viewStatus:) || - action == @selector(viewTriggers:)) + if (action == @selector(viewStructure) || + action == @selector(viewContent) || + action == @selector(viewRelations) || + action == @selector(viewStatus) || + action == @selector(viewTriggers)) { return [self database] != nil && [[[tablesListInstance valueForKeyPath:@"tablesListView"] selectedRowIndexes] count]; @@ -3537,7 +3534,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewStructure:)]; + [toolbarItem setAction:@selector(viewStructure)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarTableContent]) { [toolbarItem setLabel:NSLocalizedString(@"Content", @"toolbar item label for switching to the Table Content tab")]; @@ -3551,7 +3548,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewContent:)]; + [toolbarItem setAction:@selector(viewContent)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarCustomQuery]) { [toolbarItem setLabel:NSLocalizedString(@"Query", @"toolbar item label for switching to the Run Query tab")]; @@ -3565,7 +3562,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewQuery:)]; + [toolbarItem setAction:@selector(viewQuery)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarTableInfo]) { [toolbarItem setLabel:NSLocalizedString(@"Table Info", @"toolbar item label for switching to the Table Info tab")]; @@ -3579,7 +3576,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewStatus:)]; + [toolbarItem setAction:@selector(viewStatus)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarTableRelations]) { [toolbarItem setLabel:NSLocalizedString(@"Relations", @"toolbar item label for switching to the Table Relations tab")]; @@ -3593,7 +3590,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewRelations:)]; + [toolbarItem setAction:@selector(viewRelations)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarTableTriggers]) { [toolbarItem setLabel:NSLocalizedString(@"Triggers", @"toolbar item label for switching to the Table Triggers tab")]; @@ -3607,7 +3604,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString } //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(viewTriggers:)]; + [toolbarItem setAction:@selector(viewTriggers)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarUserManager]) { [toolbarItem setLabel:NSLocalizedString(@"Users", @"toolbar item label for switching to the User Manager tab")]; @@ -4394,13 +4391,19 @@ - (void)restoreSession // Select view NSString *view = [self->spfSession objectForKey:@"view"]; - if ([view isEqualToString:@"SP_VIEW_STRUCTURE"]) [self viewStructure:self]; - else if ([view isEqualToString:@"SP_VIEW_CONTENT"]) [self viewContent:self]; - else if ([view isEqualToString:@"SP_VIEW_CUSTOMQUERY"]) [self viewQuery:self]; - else if ([view isEqualToString:@"SP_VIEW_STATUS"]) [self viewStatus:self]; - else if ([view isEqualToString:@"SP_VIEW_RELATIONS"]) [self viewRelations:self]; - else if ([view isEqualToString:@"SP_VIEW_TRIGGERS"]) [self viewTriggers:self]; - + if ([view isEqualToString:@"SP_VIEW_STRUCTURE"]) { + [self viewStructure]; + } else if ([view isEqualToString:@"SP_VIEW_CONTENT"]) { + [self viewContent]; + } else if ([view isEqualToString:@"SP_VIEW_CUSTOMQUERY"]) { + [self viewQuery]; + } else if ([view isEqualToString:@"SP_VIEW_STATUS"]) { + [self viewStatus]; + } else if ([view isEqualToString:@"SP_VIEW_RELATIONS"]) { + [self viewRelations]; + } else if ([view isEqualToString:@"SP_VIEW_TRIGGERS"]) { + [self viewTriggers]; + } [self updateWindowTitle:self]; }); @@ -4478,18 +4481,24 @@ - (void)handleSchemeCommand:(NSDictionary*)commandDict } - if([command isEqualToString:@"SelectDocumentView"]) { + if ([command isEqualToString:@"SelectDocumentView"]) { if([params count] == 2) { NSString *view = [params objectAtIndex:1]; if([view length]) { NSString *viewName = [view lowercaseString]; - if([viewName hasPrefix:@"str"]) [self viewStructure:self]; - else if([viewName hasPrefix:@"con"]) [self viewContent:self]; - else if([viewName hasPrefix:@"que"]) [self viewQuery:self]; - else if([viewName hasPrefix:@"tab"]) [self viewStatus:self]; - else if([viewName hasPrefix:@"rel"]) [self viewRelations:self]; - else if([viewName hasPrefix:@"tri"]) [self viewTriggers:self]; - + if ([viewName hasPrefix:@"str"]) { + [self viewStructure]; + } else if([viewName hasPrefix:@"con"]) { + [self viewContent]; + } else if([viewName hasPrefix:@"que"]) { + [self viewQuery]; + } else if([viewName hasPrefix:@"tab"]) { + [self viewStatus]; + } else if([viewName hasPrefix:@"rel"]) { + [self viewRelations]; + } else if([viewName hasPrefix:@"tri"]) { + [self viewTriggers]; + } [self updateWindowTitle:self]; } } @@ -5626,7 +5635,7 @@ - (BOOL)statusLoaded #pragma mark Tab view control and delegate methods //WARNING: Might be called from code in background threads -- (IBAction)viewStructure:(id)sender { +- (void)viewStructure { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save @@ -5643,7 +5652,7 @@ - (IBAction)viewStructure:(id)sender { }); } -- (IBAction)viewContent:(id)sender { +- (void)viewContent { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { @@ -5658,8 +5667,7 @@ - (IBAction)viewContent:(id)sender { }); } -- (IBAction)viewQuery:(id)sender { - +- (void)viewQuery { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { @@ -5679,9 +5687,7 @@ - (IBAction)viewQuery:(id)sender { } -- (IBAction)viewStatus:(id)sender -{ - +- (void)viewStatus { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { @@ -5704,9 +5710,7 @@ - (IBAction)viewStatus:(id)sender } -- (IBAction)viewRelations:(id)sender -{ - +- (void)viewRelations { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { @@ -5723,9 +5727,7 @@ - (IBAction)viewRelations:(id)sender } -- (IBAction)viewTriggers:(id)sender -{ - +- (void)viewTriggers { SPMainQSync(^{ // Cancel the selection if currently editing a view and unable to save if (![self couldCommitCurrentViewActions]) { @@ -6322,8 +6324,7 @@ - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame { /** * Loads the print document interface. The actual printing is done in the doneLoading delegate. */ -- (IBAction)printDocument:(id)sender -{ +- (void)printDocument { // Only display warning for the 'Table Content' view if ([self currentlySelectedView] == SPTableViewContent) { diff --git a/Source/Controllers/Other/SPHistoryController.m b/Source/Controllers/Other/SPHistoryController.m index 43fd7f74f..d189325cd 100644 --- a/Source/Controllers/Other/SPHistoryController.m +++ b/Source/Controllers/Other/SPHistoryController.m @@ -450,22 +450,22 @@ - (void) loadEntryTaskWithPosition:(NSNumber *)positionNumber if ([theDocument currentlySelectedView] != [[historyEntry objectForKey:@"view"] integerValue]) { switch ([[historyEntry objectForKey:@"view"] integerValue]) { case SPTableViewStructure: - [theDocument viewStructure:self]; + [theDocument viewStructure]; break; case SPTableViewContent: - [theDocument viewContent:self]; + [theDocument viewContent]; break; case SPTableViewCustomQuery: - [theDocument viewQuery:self]; + [theDocument viewQuery]; break; case SPTableViewStatus: - [theDocument viewStatus:self]; + [theDocument viewStatus]; break; case SPTableViewRelations: - [theDocument viewRelations:self]; + [theDocument viewRelations]; break; case SPTableViewTriggers: - [theDocument viewTriggers:self]; + [theDocument viewTriggers]; break; } if ([theDocument currentlySelectedView] != [[historyEntry objectForKey:@"view"] integerValue]) { diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 7b289a5af..e5206b021 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -9,6 +9,9 @@ import AppKit extension SPAppController { + + // MARK: - File menu actions + @IBAction func newWindow(_ sender: Any) { tabManager.newWindowForWindow() } @@ -36,4 +39,38 @@ extension SPAppController { @IBAction func importFromClipboard(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.importFromClipboard() } + + @IBAction func printDocument(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.print() + } + + // MARK: - View menu actions + + @IBAction func viewStructure(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewStructure() + } + + @IBAction func viewContent(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewContent() + } + + @IBAction func viewQuery(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewQuery() + } + + @IBAction func viewStatus(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewStatus() + } + + @IBAction func viewRelations(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewRelations() + } + + @IBAction func viewTriggers(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.viewTriggers() + } + + @IBAction func backForwardInHistory(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.backForwardInHistory(sender) + } } diff --git a/Source/Controllers/SubviewControllers/SPTablesList.m b/Source/Controllers/SubviewControllers/SPTablesList.m index c234c816c..cc67d3f15 100644 --- a/Source/Controllers/SubviewControllers/SPTablesList.m +++ b/Source/Controllers/SubviewControllers/SPTablesList.m @@ -2347,7 +2347,7 @@ - (void)_addTableWithDetails:(NSDictionary *)tableDetails // Select the newly created table and switch to the table structure view for easier setup [tableDocumentInstance loadTable:selectedTableName ofType:selectedTableType]; - [tableDocumentInstance viewStructure:self]; + [tableDocumentInstance viewStructure]; // Query the structure of all databases in the background (mainly for completion) [[tableDocumentInstance databaseStructureRetrieval] queryDbStructureInBackgroundWithUserInfo:@{@"forceUpdate" : @YES}]; From f5f268e87f141a7626e866994e6661cdc6364692 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 19:31:42 +0100 Subject: [PATCH 35/41] Finish view menu --- Source/Controllers/DataImport/SPDataImport.m | 4 +- .../MainViewControllers/SPDatabaseDocument.h | 6 +-- .../MainViewControllers/SPDatabaseDocument.m | 35 +++++----------- Source/Controllers/SPAppController.swift | 8 ++++ .../SubviewControllers/SPQueryController.m | 3 +- Source/Views/SPWindow.m | 42 ++++--------------- 6 files changed, 34 insertions(+), 64 deletions(-) diff --git a/Source/Controllers/DataImport/SPDataImport.m b/Source/Controllers/DataImport/SPDataImport.m index 8a7783f69..445dd88d6 100644 --- a/Source/Controllers/DataImport/SPDataImport.m +++ b/Source/Controllers/DataImport/SPDataImport.m @@ -1065,7 +1065,7 @@ - (void)importCSVFile:(NSString *)filename [mySQLConnection queryString:query]; if ([mySQLConnection queryErrored]) { - [[tableDocumentInstance onMainThread] showConsole:nil]; + [[tableDocumentInstance onMainThread] showConsole]; [errors appendFormat: NSLocalizedString(@"[ERROR in row %ld] %@\n", @"error text when reading of csv file gave errors"), (long)(rowsImported+1),[mySQLConnection lastErrorMessage]]; @@ -1109,7 +1109,7 @@ - (void)importCSVFile:(NSString *)filename // If an error occurred, run the queries individually to get exact line errors if (!importMethodIsUpdate && [mySQLConnection queryErrored]) { - [[tableDocumentInstance onMainThread] showConsole:nil]; + [[tableDocumentInstance onMainThread] showConsole]; if(user_defaults_get_bool_ud(SPConsoleEnableImportExportLogging, prefs) == YES){ [[SPQueryController sharedQueryController] showErrorInConsole:mySQLConnection.lastErrorMessage connection:mySQLConnection.host database:mySQLConnection.database]; } diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 8a76a499c..097b4c919 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -346,8 +346,6 @@ - (IBAction)closePasswordSheet:(id)sender; - (IBAction)showUserManager:(id)sender; - (IBAction)copyChecksumFromSheet:(id)sender; -- (IBAction)showNavigator:(id)sender; -- (IBAction)toggleNavigator:(id)sender; - (void)setQueryMode:(NSInteger)theQueryMode; - (void)doPerformQueryService:(NSString *)query; @@ -363,7 +361,6 @@ - (void)setIsSavedInBundle:(BOOL)savedInBundle; - (void)setFileURL:(NSURL *)fileURL; - (void)connect; -- (void)showConsole:(id)sender; // Accessor methods - (NSString *)host; @@ -443,6 +440,9 @@ - (void)viewRelations; - (void)viewTriggers; - (void)backForwardInHistory:(id)sender; +- (void)toggleConsole; +- (void)showConsole; +- (void)toggleNavigator; #pragma mark - SPDatabaseViewController diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 2744deb1a..6c2e78617 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -1065,8 +1065,7 @@ - (IBAction)showGotoDatabase:(id)sender /** * Shows or hides the console */ -- (void)toggleConsole:(id)sender -{ +- (void)toggleConsole { // Toggle Console will show the Console window if it isn't visible or if it isn't // the front most window and hide it if it is the front most window if ([[[SPQueryController sharedQueryController] window] isVisible] @@ -1075,29 +1074,28 @@ - (void)toggleConsole:(id)sender [[[SPQueryController sharedQueryController] window] setIsVisible:NO]; } else { - [self showConsole:nil]; + [self showConsole]; } } /** * Brings the console to the front */ -- (void)showConsole:(id)sender -{ +- (void)showConsole { SPQueryController *queryController = [SPQueryController sharedQueryController]; // If the Console window is not visible data are not reloaded (for speed). // Due to that update list if user opens the Console window. - if(![[queryController window] isVisible]) [queryController updateEntries]; + if (![[queryController window] isVisible]) { + [queryController updateEntries]; + } [[queryController window] makeKeyAndOrderFront:self]; - } /** * Clears the console by removing all of its messages */ -- (void)clearConsole:(id)sender -{ +- (void)clearConsole:(id)sender { [[SPQueryController sharedQueryController] clearConsole:sender]; } @@ -1115,25 +1113,14 @@ - (void) setQueryMode:(NSInteger)theQueryMode /** * Shows or hides the navigator */ -- (IBAction)toggleNavigator:(id)sender -{ +- (void)toggleNavigator { BOOL isNavigatorVisible = [[[SPNavigatorController sharedNavigatorController] window] isVisible]; // Show or hide the navigator [[[SPNavigatorController sharedNavigatorController] window] setIsVisible:(!isNavigatorVisible)]; - if(!isNavigatorVisible) [[SPNavigatorController sharedNavigatorController] updateEntriesForConnection:self]; - -} - -- (IBAction)showNavigator:(id)sender -{ - BOOL isNavigatorVisible = [[[SPNavigatorController sharedNavigatorController] window] isVisible]; - if (!isNavigatorVisible) { - [self toggleNavigator:sender]; - } else { - [[[SPNavigatorController sharedNavigatorController] window] makeKeyAndOrderFront:self]; + [[SPNavigatorController sharedNavigatorController] updateEntriesForConnection:self]; } } @@ -3505,7 +3492,7 @@ - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString //set up the target action [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(showConsole:)]; + [toolbarItem setAction:@selector(showConsole)]; } else if ([itemIdentifier isEqualToString:SPMainToolbarClearConsole]) { //set the text label to be displayed in the toolbar and customization palette @@ -6287,7 +6274,7 @@ - (void)closeAndDisconnect } else { [connectionController cancelConnection:self]; } - if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole:self]; + if ([[[SPQueryController sharedQueryController] window] isVisible]) [self toggleConsole]; [createTableSyntaxWindow orderOut:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index e5206b021..889b4e7b8 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -73,4 +73,12 @@ extension SPAppController { @IBAction func backForwardInHistory(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.backForwardInHistory(sender) } + + @IBAction func toggleConsole(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.toggleConsole() + } + + @IBAction func toggleNavigator(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.toggleNavigator() + } } diff --git a/Source/Controllers/SubviewControllers/SPQueryController.m b/Source/Controllers/SubviewControllers/SPQueryController.m index 66ff33a03..626f131a1 100644 --- a/Source/Controllers/SubviewControllers/SPQueryController.m +++ b/Source/Controllers/SubviewControllers/SPQueryController.m @@ -233,8 +233,7 @@ - (NSString *)infoStringForRowIndexes:(NSIndexSet *)rows includeTimestamps:(BOOL /** * Clears the console by removing all of its messages. */ -- (IBAction)clearConsole:(id)sender -{ +- (IBAction)clearConsole:(id)sender { [messagesFullSet removeAllObjects]; [messagesFilteredSet removeAllObjects]; diff --git a/Source/Views/SPWindow.m b/Source/Views/SPWindow.m index cbda96ae4..1184e7e99 100644 --- a/Source/Views/SPWindow.m +++ b/Source/Views/SPWindow.m @@ -51,16 +51,14 @@ - (BOOL)isReleasedWhenClosed { return YES; } -#pragma mark - -#pragma mark Keyboard shortcut additions +#pragma mark - Keyboard shortcut additions /** * While keyboard shortcuts are an easy way to apply code app-wide, alternate menu * items only collapse if the unmodified key matches; this method allows keyboard * shortcuts without menu equivalents for a window, or the use of different base shortcuts. */ -- (void) sendEvent:(NSEvent *)theEvent -{ +- (void) sendEvent:(NSEvent *)theEvent { if ([theEvent type] == NSEventTypeKeyDown && [[theEvent charactersIgnoringModifiers] length]) { unichar theCharacter = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; @@ -129,12 +127,10 @@ - (void) sendEvent:(NSEvent *)theEvent break; } } - [super sendEvent:theEvent]; } -#pragma mark - -#pragma mark Undo manager handling +#pragma mark - Undo manager handling /** * If this window is controlled by an SPWindowController, and thus supports being asked @@ -147,19 +143,16 @@ - (NSUndoManager *)undoManager { return [[(SPWindowController *)[self windowController] databaseDocument] undoManager]; } - return [super undoManager]; } -#pragma mark - -#pragma mark Method overrides +#pragma mark - Method overrides /** * Allow sheets to become main if necessary, for example if they are acting as an * editor for a window. */ -- (BOOL)canBecomeMainWindow -{ +- (BOOL)canBecomeMainWindow { // If this window is a sheet which is permitted to become main, respond appropriately if ([self isSheet] && isSheetWhichCanBecomeMain) { return [self isVisible]; @@ -169,7 +162,6 @@ - (BOOL)canBecomeMainWindow if ([[self attachedSheet] isKindOfClass:[SPWindow class]] && [(SPWindow *)[self attachedSheet] isSheetWhichCanBecomeMain]) { return NO; } - return [super canBecomeMainWindow]; } @@ -177,25 +169,17 @@ - (BOOL)canBecomeMainWindow * Override the standard toolbar show/hide, adding a notification that can be * used to update state. */ -- (void)toggleToolbarShown:(id)sender -{ +- (void)toggleToolbarShown:(id)sender { [super toggleToolbarShown:sender]; [[NSNotificationCenter defaultCenter] postNotificationName:SPWindowToolbarDidToggleNotification object:nil]; } -/** - * On 10.7+, allow the window to go fullscreen; do nothing on <10.7. - */ -- (void)toggleFullScreen:(id)sender -{ - if ([NSWindow instancesRespondToSelector:@selector(toggleFullScreen:)]) { - [super toggleFullScreen:sender]; - } +- (void)toggleFullScreen:(id)sender { + [super toggleFullScreen:sender]; } -- (BOOL)validateMenuItem:(NSMenuItem *)menuItem -{ +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { // If the item is the Show/Hide Toolbar menu item, override the text to allow correct translation if ([menuItem action] == @selector(toggleToolbarShown:)) { BOOL theResponse = [super validateMenuItem:menuItem]; @@ -207,18 +191,10 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem return theResponse; } - // On systems which don't support fullscreen windows, disable the fullscreen menu item - if ([menuItem action] == @selector(toggleFullScreen:)) { - if (![NSWindow instancesRespondToSelector:@selector(toggleFullScreen:)]) { - return NO; - } - } - // Allow the superclass to perform validation otherwise (if possible) if ([super respondsToSelector:@selector(validateMenuItem:)]) { return [super validateMenuItem:menuItem]; } - return YES; } From 92cfeacb246092f6856191401c5f3a17c201c51c Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 19:52:05 +0100 Subject: [PATCH 36/41] Finish database menu --- Interfaces/MainMenu.xib | 5 -- Source/Controllers/DataImport/SPDataImport.m | 2 +- .../MainViewControllers/SPCustomQuery.m | 2 +- .../MainViewControllers/SPDatabaseDocument.h | 33 +++---- .../MainViewControllers/SPDatabaseDocument.m | 89 +++++++++---------- Source/Controllers/SPAppController.swift | 62 +++++++++++++ .../SPNavigatorController.h | 1 - .../SPNavigatorController.m | 6 -- .../SubviewControllers/SPTablesList.m | 9 +- 9 files changed, 128 insertions(+), 81 deletions(-) diff --git a/Interfaces/MainMenu.xib b/Interfaces/MainMenu.xib index 5db884c72..5152d0a1b 100644 --- a/Interfaces/MainMenu.xib +++ b/Interfaces/MainMenu.xib @@ -625,11 +625,6 @@ - - - - - diff --git a/Source/Controllers/DataImport/SPDataImport.m b/Source/Controllers/DataImport/SPDataImport.m index 445dd88d6..25cdf4bce 100644 --- a/Source/Controllers/DataImport/SPDataImport.m +++ b/Source/Controllers/DataImport/SPDataImport.m @@ -689,7 +689,7 @@ - (void)importSQLFile:(NSString *)filename } // Update available databases - [[tableDocumentInstance onMainThread] setDatabases:self]; + [[tableDocumentInstance onMainThread] setDatabases]; // Update current selected database [tableDocumentInstance refreshCurrentDatabase]; diff --git a/Source/Controllers/MainViewControllers/SPCustomQuery.m b/Source/Controllers/MainViewControllers/SPCustomQuery.m index aaa44306b..9a4c3d0e0 100644 --- a/Source/Controllers/MainViewControllers/SPCustomQuery.m +++ b/Source/Controllers/MainViewControllers/SPCustomQuery.m @@ -944,7 +944,7 @@ - (void)performQueriesTask:(NSDictionary *)taskArguments // Reload table list if at least one query began with drop, alter, rename, or create if(tableListNeedsReload || databaseWasChanged) { // Build database pulldown menu - [[tableDocumentInstance onMainThread] setDatabases:self]; + [[tableDocumentInstance onMainThread] setDatabases]; if (databaseWasChanged) { // Reset the current database diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 097b4c919..2683f6e9c 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -278,21 +278,10 @@ - (SPMySQLConnection *)getConnection; // Database methods -- (IBAction)setDatabases:(id)sender; - (IBAction)chooseDatabase:(id)sender; - (void)selectDatabase:(NSString *)aDatabase item:(NSString *)anItem; -- (IBAction)addDatabase:(id)sender; -- (IBAction)alterDatabase:(id)sender; -- (IBAction)removeDatabase:(id)sender; -- (IBAction)refreshTables:(id)sender; -- (IBAction)copyDatabase:(id)sender; -- (IBAction)renameDatabase:(id)sender; - (IBAction)showMySQLHelp:(id)sender; - (IBAction)makeTableListFilterHaveFocus:(id)sender; -- (IBAction)showServerVariables:(id)sender; -- (IBAction)showServerProcesses:(id)sender; -- (IBAction)shutdownServer:(id)sender; -- (IBAction)showGotoDatabase:(id)sender; - (NSArray *)allDatabaseNames; - (NSArray *)allSystemDatabaseNames; - (NSDictionary *)getDbStructure; @@ -317,7 +306,6 @@ - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews; - (NSString *)databaseEncoding; - (void)detectDatabaseEncoding; -- (IBAction)chooseEncoding:(id)sender; - (BOOL)supportsEncoding; - (void)updateEncodingMenuWithSelectedEncoding:(NSNumber *)encodingTag; - (NSNumber *)encodingTagFromMySQLEncoding:(NSString *)mysqlEncoding; @@ -344,13 +332,11 @@ - (IBAction)closePanelSheet:(id)sender; - (IBAction)validateSaveConnectionAccessory:(id)sender; - (IBAction)closePasswordSheet:(id)sender; -- (IBAction)showUserManager:(id)sender; - (IBAction)copyChecksumFromSheet:(id)sender; - (void)setQueryMode:(NSInteger)theQueryMode; - (void)doPerformQueryService:(NSString *)query; - (void)doPerformLoadQueryService:(NSString *)query; -- (void)flushPrivileges:(id)sender; - (void)closeConnection; - (NSWindow *)getCreateTableSyntaxWindow; @@ -386,7 +372,6 @@ // Menu methods - (BOOL)validateMenuItem:(NSMenuItem *)menuItem; -- (IBAction)openDatabaseInNewTab:(id)sender; - (IBAction)saveConnectionSheet:(id)sender; - (BOOL)isCustomQuerySelected; - (IBAction)showConnectionDebugMessages:(id)sender; @@ -444,6 +429,24 @@ - (void)showConsole; - (void)toggleNavigator; +#pragma mark Database menu + +- (void)showGotoDatabase; +- (void)addDatabase:(id)sender; +- (void)removeDatabase:(id)sender; +- (void)copyDatabase; +- (void)renameDatabase; +- (void)alterDatabase; +- (void)refreshTables; +- (void)flushPrivileges; +- (void)setDatabases; +- (void)showUserManager; +- (void)chooseEncoding:(id)sender; +- (void)openDatabaseInNewTab; +- (void)showServerVariables; +- (void)showServerProcesses; +- (void)shutdownServer; + #pragma mark - SPDatabaseViewController // Accessors diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index 6c2e78617..deda38b31 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -448,7 +448,7 @@ - (void)setConnection:(SPMySQLConnection *)theConnection } // Update the database list - [self setDatabases:self]; + [self setDatabases]; [chooseDatabaseButton setEnabled:!_isWorkingLevel]; @@ -584,9 +584,10 @@ - (SPMySQLConnection *)getConnection * * This method *MUST* be called from the UI thread! */ -- (IBAction)setDatabases:(id)sender; -{ - if (!chooseDatabaseButton) return; +- (void)setDatabases { + if (!chooseDatabaseButton) { + return; + } [chooseDatabaseButton removeAllItems]; @@ -597,8 +598,6 @@ - (IBAction)setDatabases:(id)sender; [[chooseDatabaseButton menu] addItem:[NSMenuItem separatorItem]]; - - NSArray *theDatabaseList = [mySQLConnection databases]; allDatabases = [[NSMutableArray alloc] initWithCapacity:[theDatabaseList count]]; @@ -706,7 +705,7 @@ - (void)selectDatabase:(NSString *)database item:(NSString *)item /** * opens the add-db sheet and creates the new db */ -- (IBAction)addDatabase:(id)sender +- (void)addDatabase:(id)sender { if (![tablesListInstance selectionShouldChangeInTableView:nil]) return; @@ -748,14 +747,13 @@ - (IBAction)addDatabase:(id)sender /** * Show UI for the ALTER DATABASE statement - * @warning Make sure this method is only called on mysql 4.1+ servers! */ -- (IBAction)alterDatabase:(id)sender { +- (void)alterDatabase { //once the database is created the charset and collation are written //to the db.opt file regardless if they were explicity given or not. //So there is no longer a "Default" option. - NSString *currentCharset = [databaseDataInstance getDatabaseDefaultCharacterSet]; + NSString *currentCharset = [databaseDataInstance getDatabaseDefaultCharacterSet]; NSString *currentCollation = [databaseDataInstance getDatabaseDefaultCollation]; // Setup the charset and collation dropdowns @@ -843,9 +841,10 @@ Next we need to ask the user to select another connection (from the favourites l /** * Opens the copy database sheet and copies the databsae. */ -- (IBAction)copyDatabase:(id)sender -{ - if (![tablesListInstance selectionShouldChangeInTableView:nil]) return; +- (void)copyDatabase { + if (![tablesListInstance selectionShouldChangeInTableView:nil]) { + return; + } // Inform the user that we don't support copying objects other than tables and ask them if they'd like to proceed if ([tablesListInstance hasNonTableObjects]) { @@ -875,9 +874,10 @@ - (IBAction)copyDatabase:(id)sender /** * Opens the rename database sheet and renames the databsae. */ -- (IBAction)renameDatabase:(id)sender -{ - if (![tablesListInstance selectionShouldChangeInTableView:nil]) return; +- (void)renameDatabase { + if (![tablesListInstance selectionShouldChangeInTableView:nil]) { + return; + } // We currently don't support moving any objects other than tables (i.e. views, functions, procs, etc.) from one database to another // so inform the user and don't allow them to proceed. Copy/duplicate is more appropriate in this case, but with the same limitation. @@ -899,12 +899,15 @@ - (IBAction)renameDatabase:(id)sender /** * opens sheet to ask user if he really wants to delete the db */ -- (IBAction)removeDatabase:(id)sender -{ +- (void)removeDatabase:(id)sender { // No database selected, bail - if ([chooseDatabaseButton indexOfSelectedItem] == 0) return; + if ([chooseDatabaseButton indexOfSelectedItem] == 0) { + return; + } - if (![tablesListInstance selectionShouldChangeInTableView:nil]) return; + if (![tablesListInstance selectionShouldChangeInTableView:nil]) { + return; + } NSString *title = [NSString stringWithFormat:NSLocalizedString(@"Delete database '%@'?", @"delete database message"), [self database]]; NSString *message = [NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete the database '%@'? This operation cannot be undone.", @"delete database informative message"), [self database]]; @@ -916,16 +919,14 @@ - (IBAction)removeDatabase:(id)sender /** * Refreshes the tables list by calling SPTablesList's updateTables. */ -- (IBAction)refreshTables:(id)sender -{ +- (void)refreshTables { [tablesListInstance updateTables:self]; } /** * Displays the database server variables sheet. */ -- (IBAction)showServerVariables:(id)sender -{ +- (void)showServerVariables { if (!serverVariablesController) { serverVariablesController = [[SPServerVariablesController alloc] init]; @@ -938,8 +939,7 @@ - (IBAction)showServerVariables:(id)sender /** * Displays the database process list sheet. */ -- (IBAction)showServerProcesses:(id)sender -{ +- (void)showServerProcesses { if (!processListController) { processListController = [[SPProcessListController alloc] init]; @@ -949,7 +949,7 @@ - (IBAction)showServerProcesses:(id)sender [processListController displayProcessListWindow]; } -- (IBAction)shutdownServer:(id)sender { +- (void)shutdownServer { [NSAlert createDefaultAlertWithTitle:NSLocalizedString(@"Do you really want to shutdown the server?", @"shutdown server : confirmation dialog : title") message:NSLocalizedString(@"This will wait for open transactions to complete and then quit the mysql daemon. Afterwards neither you nor anyone else can connect to this database!\n\nFull management access to the server's operating system is required to restart MySQL!", @"shutdown server : confirmation dialog : message") primaryButtonTitle:NSLocalizedString(@"Shutdown", @"shutdown server : confirmation dialog : shutdown button") primaryButtonHandler:^{ if (![self->mySQLConnection serverShutdown]) { if ([self->mySQLConnection isConnected]) { @@ -1043,8 +1043,7 @@ - (NSArray *)allSchemaKeys return [[SPNavigatorController sharedNavigatorController] allSchemaKeysForConnection:[self connectionID]]; } -- (IBAction)showGotoDatabase:(id)sender -{ +- (void)showGotoDatabase { if(!gotoDatabaseController) { gotoDatabaseController = [[SPGotoDatabaseController alloc] init]; } @@ -1054,7 +1053,7 @@ - (IBAction)showGotoDatabase:(id)sender [dbList addObjectsFromArray:[self allDatabaseNames]]; [gotoDatabaseController setDatabaseList:dbList]; - if([gotoDatabaseController runModal]) { + if ([gotoDatabaseController runModal]) { [self selectDatabase:[gotoDatabaseController selectedDatabase] item:nil]; } } @@ -1651,8 +1650,7 @@ - (void)detectDatabaseEncoding /** * When sent by an NSMenuItem, will set the encoding based on the title of the menu item */ -- (IBAction)chooseEncoding:(id)sender -{ +- (void)chooseEncoding:(id)sender { [self setConnectionEncoding:[self mysqlEncodingFromEncodingTag:[NSNumber numberWithInteger:[(NSMenuItem *)sender tag]]] reloadingViews:YES]; } @@ -2268,10 +2266,8 @@ - (IBAction)closePanelSheet:(id)sender /** * Displays the user account manager. */ -- (IBAction)showUserManager:(id)sender -{ - if (!userManagerInstance) - { +- (void)showUserManager { + if (!userManagerInstance) { userManagerInstance = [[SPUserManager alloc] init]; [userManagerInstance setDatabaseDocument:self]; @@ -2311,8 +2307,7 @@ - (void)doPerformLoadQueryService:(NSString *)query { /** * Flushes the mysql privileges */ -- (void)flushPrivileges:(id)sender -{ +- (void)flushPrivileges { [mySQLConnection queryString:@"FLUSH PRIVILEGES"]; if (![mySQLConnection queryErrored]) { @@ -3105,7 +3100,7 @@ - (BOOL)saveDocumentWithFilePath:(NSString *)fileName inBackground:(BOOL)saveInB /** * Open the currently selected database in a new tab, clearing any table selection. */ -- (IBAction)openDatabaseInNewTab:(id)sender { +- (void)openDatabaseInNewTab { // Get the current state NSDictionary *allStateDetails = @{ @@ -5234,7 +5229,7 @@ - (void)_copyDatabaseWithDetails:(NSDictionary *)databaseDetails [[self onMainThread] selectDatabase:newDatabaseName item:nil]; // Update database list - [[self onMainThread] setDatabases:self]; + [[self onMainThread] setDatabases]; // inform observers that a new database was added [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPDatabaseCreatedRemovedRenamedNotification object:nil]; @@ -5268,7 +5263,7 @@ - (void)_renameDatabase [dbActionRename setConnection:[self getConnection]]; if ([dbActionRename renameDatabaseFrom:[self createDatabaseInfo] to:newDatabaseName]) { - [self setDatabases:self]; + [self setDatabases]; [self selectDatabase:newDatabaseName item:nil]; // inform observers that a new database was added [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPDatabaseCreatedRemovedRenamedNotification object:nil]; @@ -5310,7 +5305,7 @@ - (void)_addDatabase } // this refreshes the allDatabases array - [self setDatabases:self]; + [self setDatabases]; // inform observers that a new database was added [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPDatabaseCreatedRemovedRenamedNotification object:nil]; @@ -5320,11 +5315,9 @@ - (void)_addDatabase } /** - * Run ALTER statement against current db. This is the callback to alterDatabase: - * @warning Make sure this method is only called on mysql 4.1+ servers! + * Run ALTER statement against current db. */ -- (void)_alterDatabase -{ +- (void)_alterDatabase { //we'll always run the alter statement, even if old == new because after all that is what the user requested NSString *newCharset = [alterDatabaseCharsetHelper selectedCharset]; @@ -5381,7 +5374,7 @@ - (void)_removeDatabase // that's why we can run this on main thread [databaseStructureRetrieval queryDbStructureWithUserInfo:nil]; - [self setDatabases:self]; + [self setDatabases]; [tablesListInstance setConnection:mySQLConnection]; @@ -5418,7 +5411,7 @@ - (void)_selectDatabaseAndItem:(NSDictionary *)selectionDetails if ([mySQLConnection isConnected]) { // Update the database list - [[self onMainThread] setDatabases:self]; + [[self onMainThread] setDatabases]; [NSAlert createWarningAlertWithTitle:NSLocalizedString(@"Error", @"error") message:[NSString stringWithFormat:NSLocalizedString(@"Unable to select database %@.\nPlease check you have the necessary privileges to view the database, and that the database still exists.", @"message of panel when connection to db failed after selecting from popupbutton"), targetDatabaseName] callback:nil]; } diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 889b4e7b8..2d43e258b 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -81,4 +81,66 @@ extension SPAppController { @IBAction func toggleNavigator(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.toggleNavigator() } + + // MARK: - Database menu actions + + @IBAction func showGotoDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showGotoDatabase() + } + + @IBAction func addDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.addDatabase(sender) + } + + @IBAction func removeDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.removeDatabase(sender) + } + + @IBAction func copyDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.copyDatabase() + } + + @IBAction func renameDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.renameDatabase() + } + + @IBAction func alterDatabase(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.alterDatabase() + } + + @IBAction func refreshTables(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.refreshTables() + } + + @IBAction func flushPrivileges(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.flushPrivileges() + } + + @IBAction func setDatabases(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.setDatabases() + } + + @IBAction func showUserManager(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showUserManager() + } + + @IBAction func chooseEncoding(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.chooseEncoding(sender) + } + + @IBAction func openDatabaseInNewTab(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.openDatabaseInNewTab() + } + + @IBAction func showServerVariables(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showServerVariables() + } + + @IBAction func showServerProcesses(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showServerProcesses() + } + + @IBAction func shutdownServer(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.shutdownServer() + } } diff --git a/Source/Controllers/SubviewControllers/SPNavigatorController.h b/Source/Controllers/SubviewControllers/SPNavigatorController.h index 7e70b2d0e..08f1365df 100644 --- a/Source/Controllers/SubviewControllers/SPNavigatorController.h +++ b/Source/Controllers/SubviewControllers/SPNavigatorController.h @@ -94,6 +94,5 @@ - (void)selectInActiveDocumentItem:(id)item fromView:(id)outlineView; - (BOOL)schemaPathExistsForConnection:(NSString*)connectionID andDatabase:(NSString*)dbname; -- (void)removeDatabase:(NSString*)db_id forConnectionID:(NSString*)connectionID; @end diff --git a/Source/Controllers/SubviewControllers/SPNavigatorController.m b/Source/Controllers/SubviewControllers/SPNavigatorController.m index accc2b6b8..0bf0ab326 100644 --- a/Source/Controllers/SubviewControllers/SPNavigatorController.m +++ b/Source/Controllers/SubviewControllers/SPNavigatorController.m @@ -481,12 +481,6 @@ - (BOOL)schemaPathExistsForConnection:(NSString*)connectionID andDatabase:(NSStr return NO; } -- (void)removeDatabase:(NSString*)db_id forConnectionID:(NSString*)connectionID -{ - [[schemaData objectForKey:connectionID] removeObjectForKey:db_id]; - [outlineSchema2 reloadData]; -} - - (NSDictionary *)dbStructureForConnection:(NSString*)connectionID { if([schemaData objectForKey:connectionID]) diff --git a/Source/Controllers/SubviewControllers/SPTablesList.m b/Source/Controllers/SubviewControllers/SPTablesList.m index cc67d3f15..28756bc0a 100644 --- a/Source/Controllers/SubviewControllers/SPTablesList.m +++ b/Source/Controllers/SubviewControllers/SPTablesList.m @@ -590,7 +590,7 @@ - (IBAction)copyTable:(id)sender if ([tablesListView numberOfSelectedRows] != 1) return; if (![tableSourceInstance saveRowOnDeselect] || ![tableContentInstance saveRowOnDeselect]) return; - [[self onMainThread] setDatabases:nil]; + [[self onMainThread] setDatabases]; [[tableDocumentInstance parentWindowControllerWindow] endEditingFor:nil]; @@ -637,9 +637,10 @@ - (IBAction)copyTable:(id)sender } -- (IBAction)setDatabases:(id)sender; -{ - if (!chooseDatabaseButton) return; +- (void)setDatabases { + if (!chooseDatabaseButton) { + return; + } [chooseDatabaseButton removeAllItems]; From 23b77f06cc71249b8f9bd57fd4bdd5789ccaa7dd Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 20:07:44 +0100 Subject: [PATCH 37/41] Rewamp table menu --- .../MainViewControllers/SPDatabaseDocument.h | 23 +++++----- .../MainViewControllers/SPDatabaseDocument.m | 32 +++++--------- .../TableContent/SPTableContent.h | 2 +- .../TableContent/SPTableContent.m | 3 +- Source/Controllers/SPAppController.swift | 42 +++++++++++++++++++ 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 2683f6e9c..6b3ac12c0 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -312,18 +312,8 @@ - (NSString *)mysqlEncodingFromEncodingTag:(NSNumber *)encodingTag; // Table methods -- (IBAction)showCreateTableSyntax:(id)sender; -- (IBAction)copyCreateTableSyntax:(id)sender; -- (IBAction)checkTable:(id)sender; -- (IBAction)analyzeTable:(id)sender; -- (IBAction)optimizeTable:(id)sender; -- (IBAction)repairTable:(id)sender; -- (IBAction)flushTable:(id)sender; -- (IBAction)checksumTable:(id)sender; - (IBAction)saveCreateSyntax:(id)sender; - (IBAction)copyCreateTableSyntaxFromSheet:(id)sender; -- (IBAction)focusOnTableContentFilter:(id)sender; -- (IBAction)showFilterTable:(id)sender; - (IBAction)exportSelectedTablesAs:(id)sender; - (IBAction)multipleLineEditingButtonClicked:(NSButton *)sender; @@ -447,6 +437,19 @@ - (void)showServerProcesses; - (void)shutdownServer; +#pragma mark Table menu + +- (void)focusOnTableContentFilter; +- (void)showFilterTable; +- (void)copyCreateTableSyntax; +- (void)showCreateTableSyntax:(SPDatabaseDocument *)sender; +- (void)checkTable; +- (void)repairTable; +- (void)analyzeTable; +- (void)optimizeTable; +- (void)flushTable; +- (void)checksumTable; + #pragma mark - SPDatabaseViewController // Accessors diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index deda38b31..ce91fc05b 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -1668,8 +1668,7 @@ - (BOOL)supportsEncoding /** * Copies if sender == self or displays or the CREATE TABLE syntax of the selected table(s) to the user . */ -- (IBAction)showCreateTableSyntax:(id)sender -{ +- (void)showCreateTableSyntax:(SPDatabaseDocument *)sender { NSInteger colOffs = 1; NSString *query = nil; NSString *typeString = @""; @@ -1784,8 +1783,7 @@ - (IBAction)showCreateTableSyntax:(id)sender /** * Copies the CREATE TABLE syntax of the selected table to the pasteboard. */ -- (IBAction)copyCreateTableSyntax:(id)sender -{ +- (void)copyCreateTableSyntax { [self showCreateTableSyntax:self]; return; @@ -1794,8 +1792,7 @@ - (IBAction)copyCreateTableSyntax:(id)sender /** * Performs a MySQL check table on the selected table and presents the result to the user via an alert sheet. */ -- (IBAction)checkTable:(id)sender -{ +- (void)checkTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -1853,8 +1850,7 @@ - (IBAction)checkTable:(id)sender /** * Analyzes the selected table and presents the result to the user via an alert sheet. */ -- (IBAction)analyzeTable:(id)sender -{ +- (void)analyzeTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -1912,8 +1908,7 @@ - (IBAction)analyzeTable:(id)sender /** * Optimizes the selected table and presents the result to the user via an alert sheet. */ -- (IBAction)optimizeTable:(id)sender -{ +- (void)optimizeTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -1972,8 +1967,7 @@ - (IBAction)optimizeTable:(id)sender /** * Repairs the selected table and presents the result to the user via an alert sheet. */ -- (IBAction)repairTable:(id)sender -{ +- (void)repairTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -2031,8 +2025,7 @@ - (IBAction)repairTable:(id)sender /** * Flush the selected table and inform the user via a dialog sheet. */ -- (IBAction)flushTable:(id)sender -{ +- (void)flushTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -2091,8 +2084,7 @@ - (IBAction)flushTable:(id)sender /** * Runs a MySQL checksum on the selected table and present the result to the user via an alert sheet. */ -- (IBAction)checksumTable:(id)sender -{ +- (void)checksumTable { NSArray *selectedItems = [tablesListInstance selectedTableItems]; id message = nil; @@ -2184,8 +2176,7 @@ - (IBAction)copyCreateTableSyntaxFromSheet:(id)sender /** * Switches to the content view and makes the filter field the first responder (has focus). */ -- (IBAction)focusOnTableContentFilter:(id)sender -{ +- (void)focusOnTableContentFilter { [self viewContent]; [tableContentInstance performSelector:@selector(makeContentFilterHaveFocus) withObject:nil afterDelay:0.1]; @@ -2194,11 +2185,10 @@ - (IBAction)focusOnTableContentFilter:(id)sender /** * Switches to the content view and makes the advanced filter view the first responder */ -- (IBAction)showFilterTable:(id)sender -{ +- (void)showFilterTable { [self viewContent]; - [tableContentInstance performSelector:@selector(showFilterTable:) withObject:sender afterDelay:0.1]; + [tableContentInstance performSelector:@selector(showFilterTable) withObject:nil afterDelay:0.1]; } /** diff --git a/Source/Controllers/MainViewControllers/TableContent/SPTableContent.h b/Source/Controllers/MainViewControllers/TableContent/SPTableContent.h index 3242346a4..9fe2760a7 100644 --- a/Source/Controllers/MainViewControllers/TableContent/SPTableContent.h +++ b/Source/Controllers/MainViewControllers/TableContent/SPTableContent.h @@ -200,7 +200,7 @@ typedef NS_ENUM(NSInteger, SPTableContentFilterSource) { - (IBAction)removeRow:(id)sender; // Filter Table -- (IBAction)showFilterTable:(id)sender; +- (void)showFilterTable; // Data accessors - (NSArray *)currentResult; diff --git a/Source/Controllers/MainViewControllers/TableContent/SPTableContent.m b/Source/Controllers/MainViewControllers/TableContent/SPTableContent.m index 5f859d357..883af8d4d 100644 --- a/Source/Controllers/MainViewControllers/TableContent/SPTableContent.m +++ b/Source/Controllers/MainViewControllers/TableContent/SPTableContent.m @@ -3177,8 +3177,7 @@ - (void)saveViewCellValue:(id)anObject forTableColumn:(NSTableColumn *)aTableCol /** * Show filter table */ -- (IBAction)showFilterTable:(id)sender -{ +- (void)showFilterTable { [filterTableController showFilterTableWindow]; } diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 2d43e258b..5e033c018 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -143,4 +143,46 @@ extension SPAppController { @IBAction func shutdownServer(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.shutdownServer() } + + // MARK: - Table menu actions + + @IBAction func focusOnTableContentFilter(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.focusOnTableContentFilter() + } + + @IBAction func showFilterTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showFilterTable() + } + + @IBAction func copyCreateTableSyntax(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.copyCreateTableSyntax() + } + + @IBAction func showCreateTableSyntax(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showCreateTableSyntax(nil) + } + + @IBAction func checkTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.checkTable() + } + + @IBAction func repairTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.repairTable() + } + + @IBAction func analyzeTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.analyzeTable() + } + + @IBAction func optimizeTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.optimizeTable() + } + + @IBAction func flushTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.flushTable() + } + + @IBAction func checksumTable(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.checksumTable() + } } From 1d0d36da0f789cf27783fc38472447ff82be7673 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 20:08:27 +0100 Subject: [PATCH 38/41] Move to the end of database document header --- .../MainViewControllers/SPDatabaseDocument.h | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index 6b3ac12c0..c0c244db1 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -396,6 +396,35 @@ - (SPConnectionController*)connectionController; +#pragma mark - SPDatabaseViewController + +// Accessors +- (NSString *)table; +- (SPTableType)tableType; + +- (BOOL)structureLoaded; +- (BOOL)contentLoaded; +- (BOOL)statusLoaded; + +- (void)setStructureRequiresReload:(BOOL)reload; +- (void)setContentRequiresReload:(BOOL)reload; +- (void)setStatusRequiresReload:(BOOL)reload; +- (void)setRelationsRequiresReload:(BOOL)reload; + +// Table control +- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType; + +- (NSView *)databaseView; + +#pragma mark - SPPrintController + +- (void)startPrintDocumentOperation; +- (void)generateHTMLForPrinting; +- (void)generateTableInfoHTMLForPrinting; + +- (NSArray *)columnNames; +- (NSMutableDictionary *)connectionInformation; + #pragma mark - Menu actions called from SPAppController #pragma mark File menu @@ -450,33 +479,4 @@ - (void)flushTable; - (void)checksumTable; -#pragma mark - SPDatabaseViewController - -// Accessors -- (NSString *)table; -- (SPTableType)tableType; - -- (BOOL)structureLoaded; -- (BOOL)contentLoaded; -- (BOOL)statusLoaded; - -- (void)setStructureRequiresReload:(BOOL)reload; -- (void)setContentRequiresReload:(BOOL)reload; -- (void)setStatusRequiresReload:(BOOL)reload; -- (void)setRelationsRequiresReload:(BOOL)reload; - -// Table control -- (void)loadTable:(NSString *)aTable ofType:(SPTableType)aTableType; - -- (NSView *)databaseView; - -#pragma mark - SPPrintController - -- (void)startPrintDocumentOperation; -- (void)generateHTMLForPrinting; -- (void)generateTableInfoHTMLForPrinting; - -- (NSArray *)columnNames; -- (NSMutableDictionary *)connectionInformation; - @end From d649a5a7743c1d1ae5a0bf6735f89f7a340f6978 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 20:14:52 +0100 Subject: [PATCH 39/41] Finish menu, fix reopening --- Source/Controllers/MainViewControllers/SPDatabaseDocument.h | 5 ++++- Source/Controllers/MainViewControllers/SPDatabaseDocument.m | 3 +-- Source/Controllers/SPAppController.m | 2 +- Source/Controllers/SPAppController.swift | 6 ++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h index c0c244db1..f12757b54 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.h +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.h @@ -280,7 +280,6 @@ // Database methods - (IBAction)chooseDatabase:(id)sender; - (void)selectDatabase:(NSString *)aDatabase item:(NSString *)anItem; -- (IBAction)showMySQLHelp:(id)sender; - (IBAction)makeTableListFilterHaveFocus:(id)sender; - (NSArray *)allDatabaseNames; - (NSArray *)allSystemDatabaseNames; @@ -479,4 +478,8 @@ - (void)flushTable; - (void)checksumTable; +#pragma mark Help menu + +- (void)showMySQLHelp; + @end diff --git a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m index ce91fc05b..d5c5cd310 100644 --- a/Source/Controllers/MainViewControllers/SPDatabaseDocument.m +++ b/Source/Controllers/MainViewControllers/SPDatabaseDocument.m @@ -3129,8 +3129,7 @@ - (void)importFromClipboard { * Show the MySQL Help TOC of the current MySQL connection * Invoked by the MainMenu > Help > MySQL Help */ -- (IBAction)showMySQLHelp:(id)sender -{ +- (void)showMySQLHelp { [helpViewerClientInstance showHelpFor:SPHelpViewerSearchTOC addToHistory:YES calledByAutoHelp:NO]; [[helpViewerClientInstance helpWebViewWindow] makeKeyWindow]; } diff --git a/Source/Controllers/SPAppController.m b/Source/Controllers/SPAppController.m index c0bc44ac0..783a2ab2d 100755 --- a/Source/Controllers/SPAppController.m +++ b/Source/Controllers/SPAppController.m @@ -1465,7 +1465,7 @@ - (IBAction)viewKeyboardShortcuts:(id)sender - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { // Only create a new document (without auto-connect) when there are already no documents open. - if (![self.tabManager activeWindowController]) { + if ([self.tabManager windowControllers].count == 0) { [self.tabManager newWindowForWindow]; return NO; } diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 5e033c018..43cb0b19f 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -185,4 +185,10 @@ extension SPAppController { @IBAction func checksumTable(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.checksumTable() } + + // MARK: - Help menu actions + + @IBAction func showMySQLHelp(_ sender: Any) { + tabManager.activeWindowController?.databaseDocument.showMySQLHelp() + } } From 73f2c98465eba0266f7ce3325e4cbec427b4dcb6 Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 20:19:34 +0100 Subject: [PATCH 40/41] Improve pragma MARKs --- Source/Controllers/SPAppController.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Controllers/SPAppController.swift b/Source/Controllers/SPAppController.swift index 43cb0b19f..34d5f3eae 100644 --- a/Source/Controllers/SPAppController.swift +++ b/Source/Controllers/SPAppController.swift @@ -8,9 +8,11 @@ import AppKit +// MARK: - Menu actions + extension SPAppController { - // MARK: - File menu actions + // MARK: File menu actions @IBAction func newWindow(_ sender: Any) { tabManager.newWindowForWindow() @@ -44,7 +46,7 @@ extension SPAppController { tabManager.activeWindowController?.databaseDocument.print() } - // MARK: - View menu actions + // MARK: View menu actions @IBAction func viewStructure(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.viewStructure() @@ -82,7 +84,7 @@ extension SPAppController { tabManager.activeWindowController?.databaseDocument.toggleNavigator() } - // MARK: - Database menu actions + // MARK: Database menu actions @IBAction func showGotoDatabase(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.showGotoDatabase() @@ -144,7 +146,7 @@ extension SPAppController { tabManager.activeWindowController?.databaseDocument.shutdownServer() } - // MARK: - Table menu actions + // MARK: Table menu actions @IBAction func focusOnTableContentFilter(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.focusOnTableContentFilter() @@ -186,7 +188,7 @@ extension SPAppController { tabManager.activeWindowController?.databaseDocument.checksumTable() } - // MARK: - Help menu actions + // MARK: Help menu actions @IBAction func showMySQLHelp(_ sender: Any) { tabManager.activeWindowController?.databaseDocument.showMySQLHelp() From a7136a936caad48563da680545156208d43a090a Mon Sep 17 00:00:00 2001 From: Jakub Kaspar Date: Sat, 13 Mar 2021 22:10:40 +0100 Subject: [PATCH 41/41] Remove commented out code --- .../ConnectionView/SPConnectionController.h | 1 - .../ConnectionView/SPConnectionController.m | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h index e260eb14f..f9f5d0a20 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.h @@ -251,7 +251,6 @@ typedef NS_ENUM(NSInteger, SPConnectionTimeZoneMode) { - (IBAction)showHelp:(id)sender; - (IBAction)updateSSLInterface:(id)sender; - (IBAction)updateKeyLocationFileVisibility:(id)sender; -- (void)updateSplitViewSize; - (void)resizeTabViewToConnectionType:(NSUInteger)theType animating:(BOOL)animate; diff --git a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m index 93265c25b..56973950d 100644 --- a/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m +++ b/Source/Controllers/MainViewControllers/ConnectionView/SPConnectionController.m @@ -731,20 +731,6 @@ - (IBAction)updateKeyLocationFileVisibility:(id)sender [keySelectionPanel setShowsHiddenFiles:[prefs boolForKey:SPHiddenKeyFileVisibilityKey]]; } -/** - * Update the interface in response to external split view size changes. - */ -- (void)updateSplitViewSize -{ -// if ([dbDocument getConnection]) { -// return; -// } -// -// [connectionSplitView setDelegate:nil]; -// [connectionSplitView setPosition:[[[databaseConnectionView subviews] firstObject] frame].size.width ofDividerAtIndex:0]; -// [connectionSplitView setDelegate:self]; -} - - (IBAction)updateClearTextPlugin:(id)sender { [self _startEditingConnection];