diff options
-rw-r--r-- | chrome/app/nibs/en.lproj/BrowserWindow.xib | 24 | ||||
-rw-r--r-- | chrome/app/nibs/en.lproj/TabView.xib | 31 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 36 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_cell.mm | 20 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_controller.h | 26 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_controller.mm | 92 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_view.mm | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_view.mm | 143 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_window_controller.h | 13 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_window_controller.mm | 18 |
10 files changed, 294 insertions, 111 deletions
diff --git a/chrome/app/nibs/en.lproj/BrowserWindow.xib b/chrome/app/nibs/en.lproj/BrowserWindow.xib index d9a64e8..be26e4d 100644 --- a/chrome/app/nibs/en.lproj/BrowserWindow.xib +++ b/chrome/app/nibs/en.lproj/BrowserWindow.xib @@ -2,13 +2,13 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">9F33</string> + <string key="IBDocument.SystemVersion">9G55</string> <string key="IBDocument.InterfaceBuilderVersion">677</string> - <string key="IBDocument.AppKitVersion">949.34</string> - <string key="IBDocument.HIToolboxVersion">352.00</string> + <string key="IBDocument.AppKitVersion">949.43</string> + <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="2"/> + <integer value="56"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -44,7 +44,7 @@ <nil key="NSViewClass"/> <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> <object class="NSView" key="NSWindowView" id="1006"> - <reference key="NSNextResponder"/> + <nil key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -57,19 +57,18 @@ </object> </object> <string key="NSFrameSize">{750, 600}</string> - <reference key="NSSuperview"/> </object> <string key="NSScreenRect">{{0, 0}, {1440, 878}}</string> <string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string> </object> <object class="NSCustomView" id="1029219716"> - <nil key="NSNextResponder"/> + <reference key="NSNextResponder"/> <int key="NSvFlags">266</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSButton" id="131944810"> <reference key="NSNextResponder" ref="1029219716"/> - <int key="NSvFlags">300</int> + <int key="NSvFlags">-2147483356</int> <string key="NSFrame">{{295, 0}, {40, 27}}</string> <reference key="NSSuperview" ref="1029219716"/> <bool key="NSEnabled">YES</bool> @@ -96,7 +95,8 @@ </object> </object> </object> - <string key="NSFrameSize">{483, 25}</string> + <string key="NSFrameSize">{483, 36}</string> + <reference key="NSSuperview"/> <string key="NSClassName">TabStripView</string> </object> </object> @@ -244,9 +244,9 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{136, 256}, {750, 600}}</string> + <string>{{267, 167}, {750, 600}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{136, 256}, {750, 600}}</string> + <string>{{267, 167}, {750, 600}}</string> <boolean value="NO"/> <string>{196, 240}</string> <string>{{357, 418}, {480, 270}}</string> @@ -258,7 +258,7 @@ </object> <real value="0.000000e+00"/> <real value="0.000000e+00"/> - <string>{{160, 204}, {483, 25}}</string> + <string>{{138, 199}, {483, 36}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> diff --git a/chrome/app/nibs/en.lproj/TabView.xib b/chrome/app/nibs/en.lproj/TabView.xib index ff144f7..5cc215f 100644 --- a/chrome/app/nibs/en.lproj/TabView.xib +++ b/chrome/app/nibs/en.lproj/TabView.xib @@ -102,7 +102,7 @@ </object> <object class="NSProgressIndicator" id="58797509"> <reference key="NSNextResponder" ref="1005"/> - <int key="NSvFlags">1321</int> + <int key="NSvFlags">-2147482327</int> <object class="NSPSMatrix" key="NSDrawMatrix"/> <string key="NSFrame">{{131, 4}, {16, 16}}</string> <reference key="NSSuperview" ref="1005"/> @@ -113,24 +113,28 @@ <object class="NSButton" id="1054640993"> <reference key="NSNextResponder" ref="1005"/> <int key="NSvFlags">297</int> - <string key="NSFrame">{{134, 7}, {10, 10}}</string> + <string key="NSFrame">{{131, 5}, {15, 15}}</string> <reference key="NSSuperview" ref="1005"/> <bool key="NSEnabled">YES</bool> <object class="NSButtonCell" key="NSCell" id="348599947"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">134217728</int> - <string key="NSContents">Close</string> + <string key="NSContents"/> <object class="NSFont" key="NSSupport"> <string key="NSName">LucidaGrande</string> <double key="NSSize">1.300000e+01</double> <int key="NSfFlags">1044</int> </object> <reference key="NSControlView" ref="1054640993"/> - <int key="NSButtonFlags">-2042347265</int> - <int key="NSButtonFlags2">134</int> + <int key="NSButtonFlags">139215103</int> + <int key="NSButtonFlags2">6</int> <object class="NSCustomResource" key="NSNormalImage"> <string key="NSClassName">NSImage</string> - <string key="NSResourceName">NSStopProgressTemplate</string> + <string key="NSResourceName">close_bar</string> + </object> + <object class="NSCustomResource" key="NSAlternateImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">close_bar_p</string> </object> <string key="NSAlternateContents"/> <string key="NSKeyEquivalent"/> @@ -396,7 +400,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilderKit</string> <string>com.apple.InterfaceBuilderKit</string> - <string>{{831, 498}, {160, 25}}</string> + <string>{{799, 498}, {160, 25}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="NO"/> <string>{628, 654}</string> @@ -436,6 +440,13 @@ <object class="NSMutableArray" key="referencedPartialClassDescriptions"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">browser/cocoa/tab_strip_model_observer_bridge.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> <string key="className">TabCell</string> <string key="superclassName">NSButtonCell</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> @@ -455,14 +466,12 @@ <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> <string>backgroundButton_</string> - <string>closeButton_</string> <string>progressIndicator_</string> <string>target_</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>NSButton</string> - <string>NSButton</string> <string>NSProgressIndicator</string> <string>id</string> </object> @@ -475,10 +484,6 @@ <object class="IBPartialClassDescription"> <string key="className">TabView</string> <string key="superclassName">NSView</string> - <object class="NSMutableDictionary" key="actions"> - <string key="NS.key.0">closeTab:</string> - <string key="NS.object.0">id</string> - </object> <object class="NSMutableDictionary" key="outlets"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMutableArray" key="dict.sortedKeys"> diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 048b641..c9d325f 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -275,6 +275,18 @@ willPositionSheet:(NSWindow *)sheet return [tabStripController_ selectedTabGrowBoxRect]; } +- (void)dropTabView:(NSView *)view atIndex:(NSUInteger)index { + [tabStripController_ dropTabView:view atIndex:index]; +} + +- (NSView *)selectedTabView { + return [tabStripController_ selectedTabView]; +} + +- (TabStripController *)tabStripController { + return tabStripController_; +} + - (void)setIsLoading:(BOOL)isLoading { [toolbarController_ setIsLoading:isLoading]; } @@ -296,8 +308,8 @@ willPositionSheet:(NSWindow *)sheet [toolbarController_ focusLocationBar]; } -- (void)arrangeTabs { - NOTIMPLEMENTED(); +- (void)layoutTabs { + [tabStripController_ layoutTabs]; } - (TabWindowController*)detachTabToNewWindow:(TabView*)tabView { @@ -317,6 +329,8 @@ willPositionSheet:(NSWindow *)sheet gfx::Rect browserRect(windowRect.origin.x, windowRect.origin.y, windowRect.size.width, windowRect.size.height); + NSRect tabRect = [tabView frame]; + // Detach it from the source window, which just updates the model without // deleting the tab contents. This needs to come before creating the new // Browser because it clears the TabContents' delegate, which gets hooked @@ -336,15 +350,27 @@ willPositionSheet:(NSWindow *)sheet [newBrowser->window()->GetNativeHandle() delegate]; DCHECK(controller && [controller isKindOfClass:[TabWindowController class]]); + // Force the added tab to the right size (remove stretching) + tabRect.size.height = [TabStripController defaultTabHeight]; + NSView *newTabView = [controller selectedTabView]; + [newTabView setFrame:tabRect]; + return controller; } -- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation { - NOTIMPLEMENTED(); + +- (void)insertPlaceholderForTab:(TabView*)tab + frame:(NSRect)frame + yStretchiness:(CGFloat)yStretchiness { + [tabStripController_ insertPlaceholderForTab:tab + frame:frame + yStretchiness:yStretchiness]; } - (void)removePlaceholder { - NOTIMPLEMENTED(); + [tabStripController_ insertPlaceholderForTab:nil + frame:NSZeroRect + yStretchiness:0]; } - (BOOL)isBookmarkBarVisible { diff --git a/chrome/browser/cocoa/tab_cell.mm b/chrome/browser/cocoa/tab_cell.mm index 0600c21..088f848 100644 --- a/chrome/browser/cocoa/tab_cell.mm +++ b/chrome/browser/cocoa/tab_cell.mm @@ -21,9 +21,6 @@ } - (NSBackgroundStyle)interiorBackgroundStyle { - // GTMThemeStyle style = - // [self isHighlighted] ? GTMThemeStyleTabBarSelected - // : GTMThemeStyleTabBarDeselected; return [[GTMTheme defaultTheme] interiorBackgroundStyleForStyle:GTMThemeStyleTabBarSelected active:YES]; @@ -97,7 +94,6 @@ active:active]; // Stroke with a translucent black [[NSColor colorWithCalibratedWhite:0.0 alpha:active ? 0.3 : 0.1] set]; - [path fill]; } [[NSGraphicsContext currentContext] saveGraphicsState]; @@ -105,17 +101,27 @@ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; [path setLineWidth:selected ? 2.0 : 1.0]; [path stroke]; + [[NSGraphicsContext currentContext] restoreGraphicsState]; [gradient drawInBezierPath:path angle:90.0]; - [[NSColor darkGrayColor] set]; + + if (!selected) { + [path addClip]; + NSRect borderRect, contentRect; + NSDivideRect(rect, &borderRect, &contentRect, 1, NSMaxYEdge); + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.4] set]; + NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); + } [[NSGraphicsContext currentContext] restoreGraphicsState]; // Inset where the text and favicon are drawn to keep them away from the - // sloping edges of the tab. + // sloping edges of the tab and the close box. int kInteriorInset = cellFrame.size.height / 2.0; - [self drawInteriorWithFrame:NSInsetRect(cellFrame, kInteriorInset, 0) + NSRect frame = NSInsetRect(cellFrame, kInteriorInset, 0); + frame.size.width -= 16; // Inset for close box + [self drawInteriorWithFrame:frame inView:controlView]; } diff --git a/chrome/browser/cocoa/tab_strip_controller.h b/chrome/browser/cocoa/tab_strip_controller.h index d4bd199..28e5ff0 100644 --- a/chrome/browser/cocoa/tab_strip_controller.h +++ b/chrome/browser/cocoa/tab_strip_controller.h @@ -11,6 +11,7 @@ #include "base/scoped_ptr.h" #import "chrome/browser/cocoa/tab_controller_target.h" +@class TabView; @class TabStripView; class TabStripModelObserverBridge; @@ -45,6 +46,11 @@ class ToolbarModel; // an array of TabControllers which manage the actual tab views. As above, // this is kept in the same order as the tab strip model. scoped_nsobject<NSMutableArray> tabArray_; + + // These values are only used during a drag, and override tab positioning + TabView* placeholderTab_; // weak. Tab being dragged + NSRect placeholderFrame_; // Frame to use + CGFloat placeholderStretchiness_; // Vertical force indicated by streching tab } // Initialize the controller with a view and browser that contains @@ -60,9 +66,29 @@ class ToolbarModel; // in the coordinate system of the content area of the currently selected tab. - (NSRect)selectedTabGrowBoxRect; +// Return the view for the currently selected tab. +- (NSView *)selectedTabView; + +// Drop a tab view at a new index in the array. +- (void)dropTabView:(NSView *)view atIndex:(NSUInteger)index; + // Given a tab view in the strip, return its index. Returns -1 if not present. - (NSInteger)indexForTabView:(NSView*)view; +// return the view at a given index +- (NSView*)viewAtIndex:(NSUInteger)index; + +// Set the placeholder for a dragged tab, allowing the |frame| and |strechiness| +// to be specified. This causes this tab to be rendered in an arbitrary position +- (void)insertPlaceholderForTab:(TabView*)tab + frame:(NSRect)frame + yStretchiness:(CGFloat)yStretchiness; + +// Force the tabs to rearrange themselves to reflect the current model +- (void)layoutTabs; + +// Default height for tabs. ++ (CGFloat)defaultTabHeight; @end #endif // CHROME_BROWSER_COCOA_TAB_STRIP_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm index 524d11c..5d33a32 100644 --- a/chrome/browser/cocoa/tab_strip_controller.mm +++ b/chrome/browser/cocoa/tab_strip_controller.mm @@ -47,6 +47,10 @@ return self; } ++ (CGFloat)defaultTabHeight { + return 24.0; +} + // Finds the associated TabContentsController at the given |index| and swaps // out the sole child of the contentArea to display its contents. - (void)swapInTabAtIndex:(NSInteger)index { @@ -119,11 +123,29 @@ // Called when the user closes a tab. Asks the model to close the tab. - (void)closeTab:(id)sender { - int index = [self indexForTabView:sender]; - if (index >= 0 && tabModel_->ContainsIndex(index)) - tabModel_->CloseTabContentsAt(index); + if ([self numberOfTabViews] > 1) { + int index = [self indexForTabView:sender]; + if (index >= 0 && tabModel_->ContainsIndex(index)) + tabModel_->CloseTabContentsAt(index); + } else { + // Use the standard window close if this is the last tab + // this prevents the tab from being removed from the model until after + // the window dissapears + [[tabView_ window] performClose:nil]; + } +} + + +- (void)insertPlaceholderForTab:(TabView*)tab + frame:(NSRect)frame + yStretchiness:(CGFloat)yStretchiness { + placeholderTab_ = tab; + placeholderFrame_ = frame; + placeholderStretchiness_ = yStretchiness; + [self layoutTabs]; } + // Lay out all tabs in the order of their TabContentsControllers, which matches // the ordering in the TabStripModel. This call isn't that expensive, though // it is O(n) in the number of tabs. Tabs will animate to their new position @@ -152,24 +174,45 @@ kMaxTabWidth), kMinTabWidth); + CGFloat minX = NSMinX(placeholderFrame_); + + NSUInteger i = 0; + NSInteger gap = -1; for (TabController* tab in tabArray_.get()) { - // BOOL isPlaceholder = ![[[tab view] superview] isEqual:tabView_]; - BOOL isPlaceholder = NO; + BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_]; NSRect tabFrame = [[tab view] frame]; - // If the tab is all the way on the left, we consider it a new tab. We - // need to show it, but not animate the movement. We do however want to - // animate the display. - BOOL newTab = NSMinX(tabFrame) == 0; + tabFrame.size.height = [[self class] defaultTabHeight]; + tabFrame.origin.y = 0; + tabFrame.origin.x = offset; + + // If the tab is hidden, we consider it a new tab. We make it visible + // and animate it in. + BOOL newTab = [[tab view] isHidden]; if (newTab) { - id visibilityTarget = visible ? [[tab view] animator] : [tab view]; - [visibilityTarget setHidden:NO]; + [[tab view] setHidden:NO]; } - tabFrame.origin = NSMakePoint(offset, 0); - if (!isPlaceholder) { - // Set the tab's new frame and animate the tab to its new location. Don't - // animate if the window isn't visible or if the tab is new. - BOOL animate = visible && !newTab; - id frameTarget = animate ? [[tab view] animator] : [tab view]; + + if (isPlaceholder) { + tabFrame.origin.x = placeholderFrame_.origin.x; + tabFrame.size.height += 10.0 * placeholderStretchiness_; + [[tab view] setFrame:tabFrame]; + continue; + } else { + // If our left edge is to the left of the placeholder's left, but our mid + // is to the right of it we should slide over to make space for it. + if (placeholderTab_ && gap < 0 && NSMidX(tabFrame) > minX) { + gap = i; + offset += NSWidth(tabFrame); + offset -= kTabOverlap; + tabFrame.origin.x = offset; + } + + // Animate the tab in by putting it below the horizon. + if (newTab && visible) { + [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))]; + } + + id frameTarget = visible ? [[tab view] animator] : [tab view]; tabFrame.size.width = [tab selected] ? kMaxTabWidth : baseTabWidth; [frameTarget setFrame:tabFrame]; } @@ -178,11 +221,13 @@ offset += NSWidth(tabFrame); offset -= kTabOverlap; } + i++; } // Move the new tab button into place [[newTabButton_ animator] setFrameOrigin: NSMakePoint(MIN(availableWidth, offset + kNewTabButtonOffset), 0)]; + if (i > 0) [[newTabButton_ animator] setHidden:NO]; [NSAnimationContext endGrouping]; } @@ -222,6 +267,9 @@ TabController* newController = [self newTab]; [tabArray_ insertObject:newController atIndex:index]; NSView* newView = [newController view]; + [newView setFrame:NSOffsetRect([newView frame], + 0, [[self class] defaultTabHeight])]; + [tabView_ addSubview:newView positioned:inForeground ? NSWindowAbove : NSWindowBelow relativeTo:nil]; @@ -301,6 +349,16 @@ [updatedController tabDidChange:contents]; } +- (NSView *)selectedTabView { + int selectedIndex = tabModel_->selected_index(); + return [self viewAtIndex:selectedIndex]; +} + +- (void)dropTabView:(NSView *)view atIndex:(NSUInteger)index { + // TODO(pinkerton): implement drop + NOTIMPLEMENTED(); +} + // Return the rect, in WebKit coordinates (flipped), of the window's grow box // in the coordinate system of the content area of the currently selected tab. - (NSRect)selectedTabGrowBoxRect { diff --git a/chrome/browser/cocoa/tab_strip_view.mm b/chrome/browser/cocoa/tab_strip_view.mm index d63d6ef..fd61766 100644 --- a/chrome/browser/cocoa/tab_strip_view.mm +++ b/chrome/browser/cocoa/tab_strip_view.mm @@ -18,7 +18,7 @@ NSRect boundsRect = [self bounds]; NSRect borderRect, contentRect; NSDivideRect(boundsRect, &borderRect, &contentRect, 1, NSMinYEdge); - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.3] set]; NSRectFillUsingOperation(borderRect, NSCompositeSourceOver); } diff --git a/chrome/browser/cocoa/tab_view.mm b/chrome/browser/cocoa/tab_view.mm index 2aef856..fd31652 100644 --- a/chrome/browser/cocoa/tab_view.mm +++ b/chrome/browser/cocoa/tab_view.mm @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "chrome/browser/cocoa/tab_view.h" - #include "chrome/browser/cocoa/tab_window_controller.h" @implementation TabView @@ -44,6 +43,8 @@ // ideas of dragging cocoa views between windows and how the Browser and // TabStrip models want to manage tabs. - (void)mouseDown:(NSEvent *)theEvent { + static const CGFloat kTearDistance = 36.0; + // Make sure the controller doesn't go away while we're doing this. // TODO(pinkerton): cole had this, not sure why it's necessary. [[controller_ retain] autorelease]; @@ -53,26 +54,63 @@ [[controller_ target] performSelector:[controller_ action] withObject:self]; - // TODO(pinkerton): necessary to pre-arrange the tabs here? - // Resolve overlay back to original window. NSWindow* sourceWindow = [self window]; if ([sourceWindow isKindOfClass:[NSPanel class]]) { sourceWindow = [sourceWindow parentWindow]; } + TabWindowController* sourceController = [sourceWindow windowController]; - TabWindowController* draggedController = nil; - TabWindowController* targetController = nil; // We don't want to "tear off" a tab if there's only one in the window. Treat - // it like we're dragging around a tab we've already detached. - BOOL isLastRemainingTab = [sourceController numberOfTabs] == 1; + // it like we're dragging around a tab we've already detached. Note that + // unit tests might have |-numberOfTabs| reporting zero since the model + // won't be fully hooked up. We need to be prepared for that and not send + // them into the "magnetic" codepath. + BOOL isLastRemainingTab = [sourceController numberOfTabs] <= 1; - NSWindow* dragWindow = nil; - NSWindow* dragOverlay = nil; BOOL dragging = YES; BOOL moved = NO; + NSPoint lastPoint = + [[theEvent window] convertBaseToScreen:[theEvent locationInWindow]]; + + // First, go through the magnetic drag cycle. We break out of this if + // "stretchiness" ever exceeds the a set amount. + NSRect frame = [self frame]; + if (!isLastRemainingTab) { + while (dragging) { + theEvent = + [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode dequeue:YES]; + NSPoint thisPoint = [NSEvent mouseLocation]; + CGFloat stretchiness = thisPoint.y - lastPoint.y; + stretchiness = copysign(sqrtf(fabs(stretchiness))/sqrtf(kTearDistance), + stretchiness); + [sourceController insertPlaceholderForTab:self + frame:NSOffsetRect(frame, + thisPoint.x - lastPoint.x, 0) + yStretchiness:stretchiness]; + + CGFloat tearForce = fabs(thisPoint.y - lastPoint.y); + if (tearForce > kTearDistance) break; + if ([theEvent type] == NSLeftMouseUp) { + // Mouse up, break out of the drag event tracking loop + dragging = NO; + break; + } + } + } + + [sourceController removePlaceholder]; + + TabWindowController* draggedController = nil; + TabWindowController* targetController = nil; + + NSWindow* dragWindow = nil; + NSWindow* dragOverlay = nil; + // Do not start dragging until the user has "torn" the tab off by // moving more than 3 pixels. BOOL torn = NO; @@ -81,9 +119,6 @@ NSDate* targetDwellDate = nil; // The date this target was first chosen NSMutableArray* targets = [NSMutableArray array]; - NSPoint lastPoint = - [[theEvent window] convertBaseToScreen:[theEvent locationInWindow]]; - while (dragging) { theEvent = [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask @@ -91,16 +126,13 @@ inMode:NSDefaultRunLoopMode dequeue:YES]; NSPoint thisPoint = [NSEvent mouseLocation]; - // TODO(alcor): Pinkerton indicated that cole is adding a more - // formal concept of "magnetism" to tab detachment, which would - // be an alternative solution. if (!torn) { double dx = thisPoint.x - lastPoint.x; double dy = thisPoint.y - lastPoint.y; if (dx * dx + dy * dy < kDragStartDistance * kDragStartDistance - && [theEvent type] == NSLeftMouseDragged) { - continue; + && [theEvent type] == NSLeftMouseDragged) { + continue; } torn = YES; } @@ -125,7 +157,11 @@ for (TabWindowController* target in targets) { NSRect windowFrame = [[target window] frame]; if (NSPointInRect(thisPoint, windowFrame)) { - if (NSPointInRect(thisPoint, [[target tabStripView] frame])) { + NSRect tabStripFrame = [[target tabStripView] frame]; + tabStripFrame = [[target tabStripView] convertRectToBase:tabStripFrame]; + tabStripFrame.origin = [[target window] + convertBaseToScreen:tabStripFrame.origin]; + if (NSPointInRect(thisPoint, tabStripFrame)) { newTarget = target; } break; @@ -136,7 +172,7 @@ // target and reset how long we've been hovering over this new one. if (targetController != newTarget) { targetDwellDate = [NSDate date]; - [targetController arrangeTabs]; + [targetController removePlaceholder]; targetController = newTarget; } @@ -161,8 +197,12 @@ [draggedController showOverlay]; dragOverlay = [draggedController overlayWindow]; - if (![targets count]) - [dragOverlay setHasShadow:NO]; + NSPoint origin = [sourceWindow frame].origin; + + origin.y += thisPoint.y - lastPoint.y; + [dragWindow setFrameOrigin:NSMakePoint(origin.x, origin.y)]; + //if (![targets count]) + // [dragOverlay setHasShadow:NO]; } else { NSPoint origin = [dragWindow frame].origin; origin.x += thisPoint.x - lastPoint.x; @@ -173,9 +213,7 @@ // If we're not hovering over any window, make the window is fully // opaque. Otherwise, find where the tab might be dropped and insert // a placeholder so it appears like it's part of that window. - if (!targetController) { - [[dragWindow animator] setAlphaValue:1.0]; - } else { + if (targetController) { if (![[targetController window] isKeyWindow]) { // && ([targetDwellDate timeIntervalSinceNow] < -REQUIRED_DWELL)) { [[targetController window] makeKeyAndOrderFront:nil]; @@ -186,21 +224,30 @@ // Compute where placeholder should go and insert it into the // destination tab strip. NSRect dropTabFrame = [[targetController tabStripView] frame]; + NSView *draggedTabView = [draggedController selectedTabView]; + NSRect tabFrame = [draggedTabView frame]; + tabFrame = [draggedTabView convertRectToBase:[self bounds]]; + tabFrame.origin = [dragWindow + convertBaseToScreen:tabFrame.origin]; + tabFrame.origin = [[targetController window] + convertScreenToBase:tabFrame.origin]; + tabFrame = [[targetController tabStripView] + convertRectFromBase:tabFrame]; NSPoint point = [sourceWindow convertBaseToScreen: [self convertPointToBase:NSZeroPoint]]; - int x = NSWidth([self bounds]) / 2 + point.x - dropTabFrame.origin.x; - [targetController insertPlaceholderForTab:self atLocation:x]; - [targetController arrangeTabs]; - - if (!targetController) - [dragWindow makeKeyAndOrderFront:nil]; - [[dragWindow animator] setAlphaValue:targetController ? 0.0 : 0.333]; - - [[[draggedController overlayWindow] animator] - setAlphaValue:targetController ? 0.85 : 1.0]; - // [setAlphaValue:targetController ? 0.0 : 0.6]; + [targetController insertPlaceholderForTab:self + frame:tabFrame + yStretchiness:0]; + [targetController layoutTabs]; + } else { + [dragWindow makeKeyAndOrderFront:nil]; } + + [dragWindow setHasShadow:NO]; + [dragWindow setAlphaValue:targetController ? 0.1 : 0.5]; + [[draggedController overlayWindow] + setAlphaValue:targetController ? 0.85 : 1.0]; } else if (type == NSLeftMouseUp) { // Mouse up, break out of the drag event tracking loop dragging = NO; @@ -212,38 +259,38 @@ // and clean up. if (moved) { TabWindowController *dropController = targetController; +#if 1 + dropController = nil; // Don't allow drops on other windows for now +#endif if (dropController) { -#if 0 -// TODO(alcor/pinkerton): hookup drops on existing windows + // TODO(alcor/pinkerton): hookup drops on existing windows NSRect adjustedFrame = [self bounds]; NSRect dropTabFrame = [[dropController tabStripView] frame]; adjustedFrame.origin = [self convertPointToBase:NSZeroPoint]; adjustedFrame.origin = - [sourceWindow convertBaseToScreen:adjustedFrame.origin]; + [sourceWindow convertBaseToScreen:adjustedFrame.origin]; adjustedFrame.origin.x = adjustedFrame.origin.x - dropTabFrame.origin.x; -// adjustedFrame.origin.y = adjustedFrame.origin.y - dropTabFrame.origin.y; -// adjustedFrame.size.height += adjustedFrame.origin.y; + //adjustedFrame.origin.y = adjustedFrame.origin.y - dropTabFrame.origin.y; + //adjustedFrame.size.height += adjustedFrame.origin.y; adjustedFrame.origin.y = 0; - // TODO(alcor): get add tab stuff working // [dropController addTab:tab_]; - [self setFrame:adjustedFrame]; - [dropController arrangeTabs]; + [dropController layoutTabs]; [draggedController close]; [dropController showWindow:nil]; -#endif } else { + [targetController removePlaceholder]; [[dragWindow animator] setAlphaValue:1.0]; [dragOverlay setHasShadow:NO]; - [draggedController removeOverlayAfterDelay: - [[NSAnimationContext currentContext] duration]]; + [dragWindow setHasShadow:YES]; + [draggedController removeOverlay]; [dragWindow makeKeyAndOrderFront:nil]; [[draggedController window] setLevel:NSNormalWindowLevel]; - [draggedController arrangeTabs]; + [draggedController layoutTabs]; } - [sourceController arrangeTabs]; + [sourceController layoutTabs]; } } diff --git a/chrome/browser/cocoa/tab_window_controller.h b/chrome/browser/cocoa/tab_window_controller.h index 60d13de..e86c829 100644 --- a/chrome/browser/cocoa/tab_window_controller.h +++ b/chrome/browser/cocoa/tab_window_controller.h @@ -47,7 +47,7 @@ // appropriate. // Layout the tabs based on the current ordering of the model. -- (void)arrangeTabs; +- (void)layoutTabs; // Creates a new window by pulling the given tab out and placing it in // the new window. Returns the controller for the new window. The size of the @@ -55,8 +55,9 @@ - (TabWindowController*)detachTabToNewWindow:(TabView*)tabView; // Make room in the tab strip for |tab| at the given x coordinate. -// TODO(pink): is |tab| a necessary parameter? -- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation; +- (void)insertPlaceholderForTab:(TabView*)tab + frame:(NSRect)frame + yStretchiness:(CGFloat)yStretchiness; // Removes the placeholder installed by |-insertPlaceholderForTab:atLocation:|. - (void)removePlaceholder; @@ -65,6 +66,12 @@ // dragging the only tab in the window. - (NSInteger)numberOfTabs; +// Return the view of the selected tab. +- (NSView *)selectedTabView; + +// Drop a given tab view at a new index. +- (void)dropTabView:(NSView *)view atIndex:(NSUInteger)index; + // The title of the selected tab. - (NSString*)selectedTabTitle; diff --git a/chrome/browser/cocoa/tab_window_controller.mm b/chrome/browser/cocoa/tab_window_controller.mm index 89ae67f..f7e6079 100644 --- a/chrome/browser/cocoa/tab_window_controller.mm +++ b/chrome/browser/cocoa/tab_window_controller.mm @@ -79,13 +79,10 @@ [contentView addSubview:[self tabStripView]]; cachedContentView_ = [[self window] contentView]; [self moveViewsBetweenWindowAndOverlay:useOverlay]; - [overlayWindow_ setHasShadow:YES]; [[self window] addChildWindow:overlayWindow_ ordered:NSWindowAbove]; [overlayWindow_ orderFront:nil]; - [[self window] setHasShadow:NO]; } else if (!useOverlay && overlayWindow_) { DCHECK(cachedContentView_); - [[self window] setHasShadow:YES]; [[self window] setContentView:cachedContentView_]; [self moveViewsBetweenWindowAndOverlay:useOverlay]; [[self window] makeFirstResponder:cachedContentView_]; @@ -102,7 +99,16 @@ return overlayWindow_; } -- (void)arrangeTabs { +- (void)dropTabView:(NSView *)view atIndex:(NSUInteger)index { + NOTIMPLEMENTED(); +} + +- (NSView *)selectedTabView { + NOTIMPLEMENTED(); + return nil; +} + +- (void)layoutTabs { // subclass must implement NOTIMPLEMENTED(); } @@ -113,7 +119,9 @@ return NULL; } -- (void)insertPlaceholderForTab:(TabView*)tab atLocation:(NSInteger)xLocation { +- (void)insertPlaceholderForTab:(TabView*)tab + frame:(NSRect)frame + yStretchiness:(CGFloat)yStretchiness { // subclass must implement NOTIMPLEMENTED(); } |