summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-20 17:40:24 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-20 17:40:24 +0000
commitf73bae9079d1d06b07eadaf86a2b4d7338fc78f9 (patch)
treed7585ac207e13d73e6dec5d6d49b219f5e9c3eea /chrome
parent4f16943f6e3debd2456e62770deb9062b1ae0d6e (diff)
downloadchromium_src-f73bae9079d1d06b07eadaf86a2b4d7338fc78f9.zip
chromium_src-f73bae9079d1d06b07eadaf86a2b4d7338fc78f9.tar.gz
chromium_src-f73bae9079d1d06b07eadaf86a2b4d7338fc78f9.tar.bz2
Make dropped tabs animate from where they were dropped. Make room for the full width of the tab placeholder. Make tab dragging as smooth as glass.
BUG=24982, 24983 TEST=tab dragging between windows, tab dragging w/in a window. Review URL: http://codereview.chromium.org/306006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29531 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm17
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.h6
-rw-r--r--chrome/browser/cocoa/tab_strip_controller.mm31
3 files changed, 43 insertions, 11 deletions
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index d75b41e..1fa62b1 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -704,15 +704,28 @@ willPositionSheet:(NSWindow*)sheet
if (!contents)
return;
+ // Convert |view|'s frame (which starts in the source tab strip's coordinate
+ // system) to the coordinate system of the destination tab strip. This needs
+ // to be done before being detached so the window transforms can be
+ // performed.
+ NSRect destinationFrame = [view frame];
+ NSPoint tabOrigin = destinationFrame.origin;
+ tabOrigin = [[dragController tabStripView] convertPoint:tabOrigin
+ toView:nil];
+ tabOrigin = [[view window] convertBaseToScreen:tabOrigin];
+ tabOrigin = [[self window] convertScreenToBase:tabOrigin];
+ tabOrigin = [[self tabStripView] convertPoint:tabOrigin fromView:nil];
+ destinationFrame.origin = tabOrigin;
+
// Now that we have enough information about the tab, we can remove it from
// the dragging window. We need to do this *before* we add it to the new
- // window as this will removes the TabContents' delegate.
+ // window as this will remove the TabContents' delegate.
[dragController detachTabView:view];
// Deposit it into our model at the appropriate location (it already knows
// where it should go from tracking the drag). Doing this sets the tab's
// delegate to be the Browser.
- [tabStripController_ dropTabContents:contents];
+ [tabStripController_ dropTabContents:contents withFrame:destinationFrame];
} else {
// Moving within a window.
int index = [tabStripController_ indexForTabView:view];
diff --git a/chrome/browser/cocoa/tab_strip_controller.h b/chrome/browser/cocoa/tab_strip_controller.h
index db05b6c..521be75 100644
--- a/chrome/browser/cocoa/tab_strip_controller.h
+++ b/chrome/browser/cocoa/tab_strip_controller.h
@@ -58,6 +58,7 @@ class ToolbarModel;
TabView* placeholderTab_; // weak. Tab being dragged
NSRect placeholderFrame_; // Frame to use
CGFloat placeholderStretchiness_; // Vertical force shown by streching tab.
+ NSRect droppedTabFrame_; // Initial frame of a dropped tab, for animation.
// Frame targets for all the current views.
// target frames are used because repeated requests to [NSView animator].
// aren't coalesced, so we store frames to avoid redundant calls.
@@ -110,7 +111,10 @@ class ToolbarModel;
// Drop a given TabContents at the location of the current placeholder. If there
// is no placeholder, it will go at the end. Used when dragging from another
// window when we don't have access to the TabContents as part of our strip.
-- (void)dropTabContents:(TabContents*)contents;
+// |frame| is in the coordinate system of the tab strip view and represents
+// where the user dropped the new tab so it can be animated into its correct
+// location when the tab is added to the model.
+- (void)dropTabContents:(TabContents*)contents withFrame:(NSRect)frame;
// Given a tab view in the strip, return its index. Returns -1 if not present.
- (NSInteger)indexForTabView:(NSView*)view;
diff --git a/chrome/browser/cocoa/tab_strip_controller.mm b/chrome/browser/cocoa/tab_strip_controller.mm
index 58eaec22..e37fabb 100644
--- a/chrome/browser/cocoa/tab_strip_controller.mm
+++ b/chrome/browser/cocoa/tab_strip_controller.mm
@@ -96,6 +96,8 @@ static const float kIndentLeavingSpaceForControls = 64.0;
- (NSInteger)indexForContentsView:(NSView*)view;
- (void)updateFavIconForContents:(TabContents*)contents
atIndex:(NSInteger)index;
+- (void)layoutTabsWithAnimation:(BOOL)animate
+ regenerateSubviews:(BOOL)doUpdate;
@end
@implementation TabStripController
@@ -336,7 +338,7 @@ static const float kIndentLeavingSpaceForControls = 64.0;
placeholderTab_ = tab;
placeholderFrame_ = frame;
placeholderStretchiness_ = yStretchiness;
- [self layoutTabs];
+ [self layoutTabsWithAnimation:YES regenerateSubviews:NO];
}
- (BOOL)isTabFullyVisible:(TabView*)tab {
@@ -408,7 +410,7 @@ static const float kIndentLeavingSpaceForControls = 64.0;
float offset = kIndentLeavingSpaceForControls;
NSUInteger i = 0;
- NSInteger gap = -1;
+ bool hasPlaceholderGap = false;
for (TabController* tab in tabArray_.get()) {
BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
NSRect tabFrame = [[tab view] frame];
@@ -443,9 +445,9 @@ static const float kIndentLeavingSpaceForControls = 64.0;
} 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);
+ if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) {
+ hasPlaceholderGap = true;
+ offset += NSWidth(placeholderFrame_);
offset -= kTabOverlap;
tabFrame.origin.x = offset;
}
@@ -456,9 +458,15 @@ static const float kIndentLeavingSpaceForControls = 64.0;
[tab selected] ? MAX(baseTabWidth, kMinSelectedTabWidth) :
baseTabWidth;
- // Animate a new tab in by putting it below the horizon.
+ // Animate a new tab in by putting it below the horizon unless
+ // told to put it in a specific location (ie, from a drop).
if (newTab && visible && animate) {
- [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))];
+ if (NSEqualRects(droppedTabFrame_, NSZeroRect)) {
+ [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))];
+ } else {
+ [[tab view] setFrame:droppedTabFrame_];
+ droppedTabFrame_ = NSZeroRect;
+ }
}
// Check the frame by identifier to avoid redundant calls to animator.
@@ -858,9 +866,16 @@ static const float kIndentLeavingSpaceForControls = 64.0;
// Drop a given TabContents at the location of the current placeholder. If there
// is no placeholder, it will go at the end. Used when dragging from another
// window when we don't have access to the TabContents as part of our strip.
-- (void)dropTabContents:(TabContents*)contents {
+// |frame| is in the coordinate system of the tab strip view and represents
+// where the user dropped the new tab so it can be animated into its correct
+// location when the tab is added to the model.
+- (void)dropTabContents:(TabContents*)contents withFrame:(NSRect)frame {
int index = [self indexOfPlaceholder];
+ // Mark that the new tab being created should start at |frame|. It will be
+ // reset as soon as the tab has been positioned.
+ droppedTabFrame_ = frame;
+
// Insert it into this tab strip. We want it in the foreground and to not
// inherit the current tab's group.
tabModel_->InsertTabContentsAt(index, contents, true, false);