From e86375a3402b30cf3f28c308ccf63a4ca224ccae Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 27 Dec 2017 23:36:14 +0100 Subject: Merge SPWindowController (part of #2789) --- Source/SPWindowController.m | 413 ++++++++++++++++++++++++++++++- Source/SPWindowControllerDelegate.h | 39 --- Source/SPWindowControllerDelegate.m | 457 ----------------------------------- sequel-pro.xcodeproj/project.pbxproj | 6 - 4 files changed, 412 insertions(+), 503 deletions(-) delete mode 100644 Source/SPWindowControllerDelegate.h delete mode 100644 Source/SPWindowControllerDelegate.m diff --git a/Source/SPWindowController.m b/Source/SPWindowController.m index 9755cd0d..bee91aa4 100644 --- a/Source/SPWindowController.m +++ b/Source/SPWindowController.m @@ -29,12 +29,12 @@ // More info at #import "SPWindowController.h" -#import "SPWindowControllerDelegate.h" #import "SPDatabaseDocument.h" #import "SPDatabaseViewController.h" #import "SPAppController.h" #import "PSMTabDragAssistant.h" #import "SPConnectionController.h" +#import "SPFavoritesOutlineView.h" #import #import @@ -45,6 +45,12 @@ - (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem; - (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc; - (void)_selectedTableDocumentDeallocd:(NSNotification *)notification; + +#pragma mark - SPWindowControllerDelegate + +- (void)tabDragStarted:(id)sender; +- (void)tabDragStopped:(id)sender; + @end @implementation SPWindowController @@ -520,6 +526,411 @@ [self _switchOutSelectedTableDocument:nil]; } +#pragma mark - SPWindowControllerDelegate + +/** + * 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. + */ +- (BOOL)windowShouldClose:(id)sender +{ + for (NSTabViewItem *eachItem in [tabView tabViewItems]) + { + SPDatabaseDocument *eachDocument = [eachItem identifier]; + + if (![eachDocument parentTabShouldClose]) return NO; + } + + // Remove global session data if the last window of a session will be closed + if ([SPAppDelegate sessionURL] && [[SPAppDelegate orderedDatabaseConnectionWindows] count] == 1) { + [SPAppDelegate setSessionURL:nil]; + [SPAppDelegate setSpfSessionDocData:nil]; + } + + return YES; +} + +/** + * When the window does close, close all tabs. + */ +- (void)windowWillClose:(NSNotification *)notification +{ + for (NSTabViewItem *eachItem in [tabView tabViewItems]) + { + [tabView removeTabViewItem:eachItem]; + } + + [self autorelease]; +} + +/** + * When the window becomes key, inform the selected tab and + * update menu items. + */ +- (void)windowDidBecomeKey:(NSNotification *)notification +{ + [selectedTableDocument tabDidBecomeKey]; + + // Update the "Close window" item + [closeWindowMenuItem setTitle:NSLocalizedString(@"Close Window", @"Close Window menu item")]; + [closeWindowMenuItem setKeyEquivalentModifierMask:(NSCommandKeyMask | NSShiftKeyMask)]; + + // Ensure the "Close tab" item is enabled and has the standard shortcut + [closeTabMenuItem setEnabled:YES]; + [closeTabMenuItem setKeyEquivalent:@"w"]; + [closeTabMenuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; +} + +/** + * When the window resigns key, update menu items. + */ +- (void)windowDidResignKey:(NSNotification *)notification +{ + + // Disable the "Close tab" menu item + [closeTabMenuItem setEnabled:NO]; + [closeTabMenuItem setKeyEquivalent:@""]; + + // Update the "Close window" item to show only "Close" + [closeWindowMenuItem setTitle:NSLocalizedString(@"Close", @"Close menu item")]; + [closeWindowMenuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; +} + +/** + * Observe changes in main window status to update drawing state to match + */ +- (void)windowDidBecomeMain:(NSNotification *)notification +{ + +} +- (void)windowDidResignMain:(NSNotification *)notification +{ +} + +/** + * If the window is resized, notify all the tabs. + */ +- (void)windowDidResize:(NSNotification *)notification +{ + for (NSTabViewItem *eachItem in [tabView tabViewItems]) + { + SPDatabaseDocument *eachDocument = [eachItem identifier]; + + [eachDocument tabDidResize]; + } +} + +/** + * If the window is entering fullscreen, update the front tab's titlebar status view visibility. + */ +- (void)windowWillEnterFullScreen:(NSNotification *)notification +{ + [selectedTableDocument updateTitlebarStatusVisibilityForcingHide:YES]; +} + +/** + * If the window exits fullscreen, update the front tab's titlebar status view visibility. + */ +- (void)windowDidExitFullScreen:(NSNotification *)notification +{ + [selectedTableDocument updateTitlebarStatusVisibilityForcingHide:NO]; +} + +#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 +{ + [selectedTableDocument willResignActiveTabInWindow]; +} + +/** + * Called when a tab item was selected. + */ +- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem +{ + if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) return; + + [self _switchOutSelectedTableDocument:[tabViewItem identifier]]; + [selectedTableDocument didBecomeActiveTabInWindow]; + + if ([[self window] isKeyWindow]) [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 identifier]; + + 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 identifier]; + + [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 identifier]; + + // Grab a reference to the old window + NSWindow *draggedFromWindow = [draggedDocument parentWindow]; + + // 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 setParentWindowController:[[tabBarControl window] windowController]]; + [draggedDocument setParentWindow:[tabBarControl window]]; + [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 identifier]; + + 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 = [tabView indexOfTabViewItem:tabViewItem]; + + if ([[tabBar cells] count] < (NSUInteger)tabIndex) return @""; + + PSMTabBarCell *theCell = [[tabBar 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 { + if ([[tabViewItem identifier] respondsToSelector:@selector(tabTitleForTooltip)]) { + return [[tabViewItem identifier] tabTitleForTooltip]; + } + + return @""; + } +} + +/** + * 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"]; + 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; + + if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAlwaysShowWindowTabBar]) point.y += 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 identifier] parentWindow] title]]; + + // Return the window's tab bar + return [newWindowController valueForKey:@"tabBar"]; +} + +/** + * 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:(unsigned int *)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]; + [viewRep release]; + + // Calculate the titlebar+toolbar height + CGFloat contentViewOffsetY = [[self window] frame].size.height - [[[self window] contentView] frame].size.height; + offset->height = contentViewOffsetY + [tabBar frame].size.height; + + // Draw over the tab bar area + [viewImage lockFocus]; + [[NSColor windowBackgroundColor] set]; + NSRectFill([tabBar frame]); + [viewImage unlockFocus]; + + // Draw the tab bar background in the tab bar area + [viewImage lockFocus]; + NSRect tabFrame = [tabBar 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 autorelease]; +} + +/** + * 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 autorelease]; +} + +/** + * 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 +{ + [tabBar setHideForSingleTab:NO]; +} + +/** + * When tab drags stop, set tab bars to automatically hide again for only one tab. + */ +- (void)tabDragStopped:(id)sender +{ + if (![[NSUserDefaults standardUserDefaults] boolForKey:SPAlwaysShowWindowTabBar]) { + [tabBar setHideForSingleTab:YES]; + } +} + #pragma mark - - (void)dealloc diff --git a/Source/SPWindowControllerDelegate.h b/Source/SPWindowControllerDelegate.h deleted file mode 100644 index 12a2c7ea..00000000 --- a/Source/SPWindowControllerDelegate.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// SPWindowControllerDelegate.h -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on April 9, 2012. -// Copyright (c) 2012 Stuart Connolly. 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" - -@interface SPWindowController (SPWindowControllerDelegate) - -- (void)tabDragStarted:(id)sender; -- (void)tabDragStopped:(id)sender; - - -@end diff --git a/Source/SPWindowControllerDelegate.m b/Source/SPWindowControllerDelegate.m deleted file mode 100644 index ba7f6303..00000000 --- a/Source/SPWindowControllerDelegate.m +++ /dev/null @@ -1,457 +0,0 @@ -// -// SPWindowControllerDelegate.m -// sequel-pro -// -// Created by Stuart Connolly (stuconnolly.com) on April 9, 2012. -// Copyright (c) 2012 Stuart Connolly. 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 "SPWindowControllerDelegate.h" -#import "PSMTabDragAssistant.h" -#import "SPDatabaseDocument.h" -#import "SPDatabaseViewController.h" -#import "SPAppController.h" -#import "SPConnectionController.h" -#import "SPFavoritesOutlineView.h" - -#import -#import - -@interface SPWindowController (SPDeclaredAPI) - -- (void)_updateProgressIndicatorForItem:(NSTabViewItem *)theItem; -- (void)_switchOutSelectedTableDocument:(SPDatabaseDocument *)newDoc; - -@end - -@implementation SPWindowController (SPWindowControllerDelegate) - -#pragma mark - -#pragma mark Window delegate methods - -/** - * 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. - */ -- (BOOL)windowShouldClose:(id)sender -{ - for (NSTabViewItem *eachItem in [tabView tabViewItems]) - { - SPDatabaseDocument *eachDocument = [eachItem identifier]; - - if (![eachDocument parentTabShouldClose]) return NO; - } - - // Remove global session data if the last window of a session will be closed - if ([SPAppDelegate sessionURL] && [[SPAppDelegate orderedDatabaseConnectionWindows] count] == 1) { - [SPAppDelegate setSessionURL:nil]; - [SPAppDelegate setSpfSessionDocData:nil]; - } - - return YES; -} - -/** - * When the window does close, close all tabs. - */ -- (void)windowWillClose:(NSNotification *)notification -{ - for (NSTabViewItem *eachItem in [tabView tabViewItems]) - { - [tabView removeTabViewItem:eachItem]; - } - - [self autorelease]; -} - -/** - * When the window becomes key, inform the selected tab and - * update menu items. - */ -- (void)windowDidBecomeKey:(NSNotification *)notification -{ - [selectedTableDocument tabDidBecomeKey]; - - // Update the "Close window" item - [closeWindowMenuItem setTitle:NSLocalizedString(@"Close Window", @"Close Window menu item")]; - [closeWindowMenuItem setKeyEquivalentModifierMask:(NSCommandKeyMask | NSShiftKeyMask)]; - - // Ensure the "Close tab" item is enabled and has the standard shortcut - [closeTabMenuItem setEnabled:YES]; - [closeTabMenuItem setKeyEquivalent:@"w"]; - [closeTabMenuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; -} - -/** - * When the window resigns key, update menu items. - */ -- (void)windowDidResignKey:(NSNotification *)notification -{ - - // Disable the "Close tab" menu item - [closeTabMenuItem setEnabled:NO]; - [closeTabMenuItem setKeyEquivalent:@""]; - - // Update the "Close window" item to show only "Close" - [closeWindowMenuItem setTitle:NSLocalizedString(@"Close", @"Close menu item")]; - [closeWindowMenuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; -} - -/** - * Observe changes in main window status to update drawing state to match - */ -- (void)windowDidBecomeMain:(NSNotification *)notification -{ - -} -- (void)windowDidResignMain:(NSNotification *)notification -{ -} - -/** - * If the window is resized, notify all the tabs. - */ -- (void)windowDidResize:(NSNotification *)notification -{ - for (NSTabViewItem *eachItem in [tabView tabViewItems]) - { - SPDatabaseDocument *eachDocument = [eachItem identifier]; - - [eachDocument tabDidResize]; - } -} - -/** - * If the window is entering fullscreen, update the front tab's titlebar status view visibility. - */ -- (void)windowWillEnterFullScreen:(NSNotification *)notification -{ - [selectedTableDocument updateTitlebarStatusVisibilityForcingHide:YES]; -} - -/** - * If the window exits fullscreen, update the front tab's titlebar status view visibility. - */ -- (void)windowDidExitFullScreen:(NSNotification *)notification -{ - [selectedTableDocument updateTitlebarStatusVisibilityForcingHide:NO]; -} - -#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 -{ - [selectedTableDocument willResignActiveTabInWindow]; -} - -/** - * Called when a tab item was selected. - */ -- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[PSMTabDragAssistant sharedDragAssistant] isDragging]) return; - - [self _switchOutSelectedTableDocument:[tabViewItem identifier]]; - [selectedTableDocument didBecomeActiveTabInWindow]; - - if ([[self window] isKeyWindow]) [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 identifier]; - - 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 identifier]; - - [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 identifier]; - - // Grab a reference to the old window - NSWindow *draggedFromWindow = [draggedDocument parentWindow]; - - // 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 setParentWindowController:[[tabBarControl window] windowController]]; - [draggedDocument setParentWindow:[tabBarControl window]]; - [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 identifier]; - - 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 = [tabView indexOfTabViewItem:tabViewItem]; - - if ([[tabBar cells] count] < (NSUInteger)tabIndex) return @""; - - PSMTabBarCell *theCell = [[tabBar 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 { - if ([[tabViewItem identifier] respondsToSelector:@selector(tabTitleForTooltip)]) { - return [[tabViewItem identifier] tabTitleForTooltip]; - } - - return @""; - } -} - -/** - * 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"]; - 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; - - if ([[NSUserDefaults standardUserDefaults] boolForKey:SPAlwaysShowWindowTabBar]) point.y += 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 identifier] parentWindow] title]]; - - // Return the window's tab bar - return [newWindowController valueForKey:@"tabBar"]; -} - -/** - * 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:(unsigned int *)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]; - [viewRep release]; - - // Calculate the titlebar+toolbar height - CGFloat contentViewOffsetY = [[self window] frame].size.height - [[[self window] contentView] frame].size.height; - offset->height = contentViewOffsetY + [tabBar frame].size.height; - - // Draw over the tab bar area - [viewImage lockFocus]; - [[NSColor windowBackgroundColor] set]; - NSRectFill([tabBar frame]); - [viewImage unlockFocus]; - - // Draw the tab bar background in the tab bar area - [viewImage lockFocus]; - NSRect tabFrame = [tabBar 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 autorelease]; -} - -/** - * 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 autorelease]; -} - -/** - * 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 -{ - [tabBar setHideForSingleTab:NO]; -} - -/** - * When tab drags stop, set tab bars to automatically hide again for only one tab. - */ -- (void)tabDragStopped:(id)sender -{ - if (![[NSUserDefaults standardUserDefaults] boolForKey:SPAlwaysShowWindowTabBar]) { - [tabBar setHideForSingleTab:YES]; - } -} - -@end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 588b5377..294b584b 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -117,7 +117,6 @@ 17CC97F310B4ABE90034CD7A /* SPAboutController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17CC97F210B4ABE90034CD7A /* SPAboutController.m */; }; 17CC97F710B4AC6C0034CD7A /* AboutPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17CC97F510B4AC6C0034CD7A /* AboutPanel.xib */; }; 17CC993B10B4C9C80034CD7A /* License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 17CC993A10B4C9C80034CD7A /* License.rtf */; }; - 17D3583F1533768E00A654D7 /* SPWindowControllerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D3583E1533768E00A654D7 /* SPWindowControllerDelegate.m */; }; 17D38EBC12771A1C00672B13 /* SPTableStructureDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D38EBB12771A1C00672B13 /* SPTableStructureDelegate.m */; }; 17D38F701279E23A00672B13 /* SPTableFieldValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D38F6F1279E23A00672B13 /* SPTableFieldValidation.m */; }; 17D390C8127B65AF00672B13 /* SPGeneralPreferencePane.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D390C7127B65AF00672B13 /* SPGeneralPreferencePane.m */; }; @@ -830,8 +829,6 @@ 17CC97F210B4ABE90034CD7A /* SPAboutController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPAboutController.m; sourceTree = ""; }; 17CC97F610B4AC6C0034CD7A /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Interfaces/English.lproj/AboutPanel.xib; sourceTree = ""; }; 17CC993A10B4C9C80034CD7A /* License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = License.rtf; sourceTree = ""; }; - 17D3583D1533768E00A654D7 /* SPWindowControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPWindowControllerDelegate.h; sourceTree = ""; }; - 17D3583E1533768E00A654D7 /* SPWindowControllerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPWindowControllerDelegate.m; sourceTree = ""; }; 17D38EBA12771A1C00672B13 /* SPTableStructureDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPTableStructureDelegate.h; sourceTree = ""; }; 17D38EBB12771A1C00672B13 /* SPTableStructureDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPTableStructureDelegate.m; sourceTree = ""; }; 17D38F6E1279E23A00672B13 /* SPTableFieldValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPTableFieldValidation.h; sourceTree = ""; }; @@ -1870,8 +1867,6 @@ children = ( 58A8A78F11A036C000B95749 /* SPWindowController.h */, 58A8A79011A036C000B95749 /* SPWindowController.m */, - 17D3583D1533768E00A654D7 /* SPWindowControllerDelegate.h */, - 17D3583E1533768E00A654D7 /* SPWindowControllerDelegate.m */, ); name = Window; sourceTree = ""; @@ -3463,7 +3458,6 @@ 17386E0E1519257E002DC206 /* SPTableContentDelegate.m in Sources */, 17381856151FB34E0078FFE2 /* SPUserManagerDelegate.m in Sources */, 17BA2A3215275D8600389803 /* SPExportInterfaceController.m in Sources */, - 17D3583F1533768E00A654D7 /* SPWindowControllerDelegate.m in Sources */, 1798F1871550175B004B0AB8 /* SPFavoritesExporter.m in Sources */, 1798F1881550175B004B0AB8 /* SPFavoritesImporter.m in Sources */, 1798F18F1550178E004B0AB8 /* SPConnectionControllerDataSource.m in Sources */, -- cgit v1.2.3