From 93d2314ef5bb924707fb0f19e31bb914cceb5d79 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Sun, 13 Jun 2010 21:43:05 +0000 Subject: Improvements to tab dragging and switching: - Attempt to preserve toolbar visibility settings - Fix dragging on previously background tabs - When dragging a tab, show the tab bar in all windows to that windows containing a single tab can be added to - Fix window sizing when creating new windows via a tab drag - Improve window representation when dragging a tab off a window, and fix placement when creating a new window following mouse release --- Source/SPDatabaseDocument.m | 2 ++ Source/SPWindowController.m | 76 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index d5ebb24c..e0ba899e 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -3909,7 +3909,9 @@ { // Update the toolbar + BOOL toolbarVisible = ![parentWindow toolbar] || [[parentWindow toolbar] isVisible]; [parentWindow setToolbar:mainToolbar]; + if (!toolbarVisible) [[parentWindow toolbar] setVisible:NO]; // Update the window's title and represented document [self updateWindowTitle:self]; diff --git a/Source/SPWindowController.m b/Source/SPWindowController.m index 0050ba15..3b7ef8aa 100644 --- a/Source/SPWindowController.m +++ b/Source/SPWindowController.m @@ -59,6 +59,7 @@ [tabBar setCellMinWidth:100]; [tabBar setCellMaxWidth:250]; [tabBar setCellOptimumWidth:250]; + [tabBar setSelectsTabsOnMouseDown:YES]; [tabBar setTearOffStyle:PSMTabBarTearOffAlphaWindow]; // hook up add tab button @@ -68,6 +69,10 @@ // Retrieve references to the 'Close Window' and 'Close Tab' menus. These are updated as window focus changes. closeWindowMenuItem = [[[[NSApp mainMenu] itemWithTag:SPMainMenuFile] submenu] itemWithTag:1003]; closeTabMenuItem = [[[[NSApp mainMenu] itemWithTag:SPMainMenuFile] submenu] itemWithTag:1103]; + + // Register for drag start and stop notifications - used to show/hide tab bars + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tabDragStarted:) name:@"SPTabDragStart" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tabDragStopped:) name:@"SPTabDragStop" object:nil]; } /** @@ -75,6 +80,8 @@ */ - (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [managedDatabaseConnections release]; [super dealloc]; @@ -257,6 +264,7 @@ */ - (BOOL)tabView:(NSTabView *)aTabView shouldDragTabViewItem:(NSTabViewItem *)tabViewItem fromTabBar:(PSMTabBarControl *)tabBarControl { + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPTabDragStart" object:self]; return YES; } @@ -288,6 +296,8 @@ // 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]; + + [[NSNotificationCenter defaultCenter] postNotificationName:@"SPTabDragStop" object:self]; } /** @@ -346,16 +356,27 @@ return @""; } +/** + * Allow window closing of the last tab item. + */ - (void)tabView:(NSTabView *)aTabView closeWindowForLastTabViewItem:(NSTabViewItem *)tabViewItem { [[aTabView window] close]; } +/** + * 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; + 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 { @@ -363,12 +384,20 @@ 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; + } + // Tweak window positioning according to the style and toolbar point.x -= [[tabBar style] leftMarginForTabBarControl]; - point.y += 21; + point.y += 21 + toolbarHeight - kPSMTabBarControlHeight; // Set the new window position and size - [newWindow setFrame:[[self window] frame] display:NO]; + 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 @@ -376,9 +405,12 @@ // 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]; @@ -394,12 +426,46 @@ [[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 scaleXBy:1.0 yBy:-1.0]; + [transform concat]; + tabFrame.origin.y = -tabFrame.origin.y - tabFrame.size.height; + [(id )[[aTabView delegate] style] drawBackgroundInRect:tabFrame]; + [transform invert]; + [transform concat]; + [viewImage unlockFocus]; + offset->height = 21; + *styleMask = NSTitledWindowMask | NSUnifiedTitleAndToolbarWindowMask; return [viewImage 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 +{ + [tabBar setHideForSingleTab:YES]; +} + #pragma mark - #pragma mark Window delegate methods -- cgit v1.2.3