| Index: chrome/browser/cocoa/tab_strip_controller.mm
|
| ===================================================================
|
| --- chrome/browser/cocoa/tab_strip_controller.mm (revision 21504)
|
| +++ chrome/browser/cocoa/tab_strip_controller.mm (working copy)
|
| @@ -66,6 +66,14 @@
|
| initWithFrame:NSZeroRect]);
|
| [view addSubview:dragBlockingView_];
|
| newTabTargetFrame_ = NSMakeRect(0, 0, 0, 0);
|
| +
|
| + // Make sure our TabStripView posts frame change notifications, and
|
| + // register for them.
|
| + [tabView_ setPostsFrameChangedNotifications:YES];
|
| + [[NSNotificationCenter defaultCenter] addObserver:self
|
| + selector:@selector(tabViewFrameChanged:)
|
| + name:NSViewFrameDidChangeNotification
|
| + object:tabView_];
|
| }
|
| return self;
|
| }
|
| @@ -200,7 +208,7 @@
|
| // abstracting a base class interface.
|
| // TODO(pinkerton): Note this doesn't do too well when the number of min-sized
|
| // tabs would cause an overflow.
|
| -- (void)layoutTabs {
|
| +- (void)layoutTabsCurrent {
|
| const float kIndentLeavingSpaceForControls = 64.0;
|
| const float kTabOverlap = 20.0;
|
| const float kNewTabButtonOffset = 8.0;
|
| @@ -330,6 +338,151 @@
|
| [dragBlockingView_ setFrame:enclosingRect];
|
| }
|
|
|
| +//////////////////////////////////////
|
| +// FIXME -- this is only temporary! //
|
| +//////////////////////////////////////
|
| +- (void)layoutTabsVeryTemp {
|
| + const float kIndentLeavingSpaceForControls = 64.0;
|
| + const float kTabOverlap = 20.0;
|
| + const float kNewTabButtonOffset = 8.0;
|
| + const float kMaxTabWidth = [TabController maxTabWidth];
|
| + const float kMinTabWidth = [TabController minTabWidth];
|
| + const float kMinSelectedTabWidth = [TabController minSelectedTabWidth];
|
| +
|
| + NSRect enclosingRect = NSZeroRect;
|
| +
|
| + // Compute the base width of tabs given how much size we have available.
|
| + float availableWidth =
|
| + NSWidth([tabView_ frame]) - NSWidth([newTabButton_ frame]) -
|
| + kNewTabButtonOffset - kIndentLeavingSpaceForControls;
|
| + // Add back in the amount we "get back" from the tabs overlapping.
|
| + availableWidth += [tabContentsArray_ count] * kTabOverlap;
|
| + const float baseTabWidth =
|
| + MAX(MIN(availableWidth / [tabContentsArray_ count],
|
| + kMaxTabWidth),
|
| + kMinTabWidth);
|
| +
|
| + CGFloat minX = NSMinX(placeholderFrame_);
|
| + BOOL visible = [[tabView_ window] isVisible];
|
| +
|
| + float offset = kIndentLeavingSpaceForControls;
|
| + NSUInteger i = 0;
|
| + NSInteger gap = -1;
|
| + NSView* previousTab = nil;
|
| + for (TabController* tab in tabArray_.get()) {
|
| + BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
|
| + NSRect tabFrame = [[tab view] frame];
|
| + 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) {
|
| + [[tab view] setHidden:NO];
|
| + }
|
| +
|
| + if (isPlaceholder) {
|
| + // Move the current tab to the correct location intantly.
|
| + tabFrame.origin.x = placeholderFrame_.origin.x;
|
| + // TODO(alcor): reenable this
|
| + //tabFrame.size.height += 10.0 * placeholderStretchiness_;
|
| + [[tab view] setFrame:tabFrame];
|
| +
|
| + // Store the frame by identifier to aviod redundant calls to animator.
|
| + NSValue *identifier = [NSValue valueWithPointer:[tab view]];
|
| + [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
|
| + forKey:identifier];
|
| + 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))];
|
| + }
|
| +
|
| + // Set the width. Selected tabs are slightly wider when things get
|
| + // really small and thus we enforce a different minimum width.
|
| + tabFrame.size.width =
|
| + [tab selected] ? MAX(baseTabWidth, kMinSelectedTabWidth) :
|
| + baseTabWidth;
|
| +
|
| + // Check the frame by identifier to avoid redundant calls to animator.
|
| + id frameTarget = [tab view];
|
| + NSValue *identifier = [NSValue valueWithPointer:[tab view]];
|
| + NSValue *oldTargetValue = [targetFrames_ objectForKey:identifier];
|
| + if (!oldTargetValue ||
|
| + !NSEqualRects([oldTargetValue rectValue], tabFrame)) {
|
| + [frameTarget setFrame:tabFrame];
|
| + [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
|
| + forKey:identifier];
|
| + }
|
| + enclosingRect = NSUnionRect(tabFrame, enclosingRect);
|
| + }
|
| +
|
| + // Ensure the current tab is "below" the tab before it in z-order so that
|
| + // all the tab overlaps are consistent. The selected tab is always the
|
| + // frontmost, but it's already been made frontmost when the tab was selected
|
| + // so we don't need to do anything about it here. It will get put back into
|
| + // place when another tab is selected.
|
| + if (![tab selected]) {
|
| + [tabView_ addSubview:[tab view]
|
| + positioned:NSWindowBelow
|
| + relativeTo:previousTab];
|
| + }
|
| + previousTab = [tab view];
|
| +
|
| + offset += NSWidth(tabFrame);
|
| + offset -= kTabOverlap;
|
| + i++;
|
| + }
|
| +
|
| + NSRect newTabNewFrame = [newTabButton_ frame];
|
| + newTabNewFrame.origin =
|
| + NSMakePoint(MIN(availableWidth, offset + kNewTabButtonOffset), 0);
|
| + newTabNewFrame.origin.x = MAX(newTabNewFrame.origin.x,
|
| + NSMaxX(placeholderFrame_));
|
| + if (i > 0 && [newTabButton_ isHidden]) {
|
| + [newTabButton_ setHidden:NO];
|
| + }
|
| +
|
| + if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) {
|
| + [newTabButton_ setFrame:newTabNewFrame];
|
| + newTabTargetFrame_ = newTabNewFrame;
|
| + // Move the new tab button into place.
|
| + }
|
| +
|
| + [dragBlockingView_ setFrame:enclosingRect];
|
| +}
|
| +
|
| +// FIXME: Properly produce a unified version of this, which handles both
|
| +// animated and unanimated cases.
|
| +- (void)layoutTabsInternal:(BOOL)doAnimate {
|
| + if (doAnimate)
|
| + [self layoutTabsCurrent];
|
| + else
|
| + [self layoutTabsVeryTemp];
|
| +}
|
| +
|
| +// Layout tabs with animation.
|
| +- (void)layoutTabs {
|
| + [self layoutTabsInternal:YES];
|
| +}
|
| +
|
| +// Layout tabs without animation.
|
| +- (void)layoutTabsFast {
|
| + [self layoutTabsInternal:NO];
|
| +}
|
| +
|
| // Handles setting the title of the tab based on the given |contents|. Uses
|
| // a canned string if |contents| is NULL.
|
| - (void)setTabTitle:(NSViewController*)tab withContents:(TabContents*)contents {
|
| @@ -626,4 +779,11 @@
|
| }
|
| }
|
|
|
| +// Called when our TabStripView's frame changes size (i.e., on window resize).
|
| +// Since resizes are tracked (and yield many events), we need to layout the
|
| +// tabs quickly.
|
| +- (void)tabViewFrameChanged:(NSNotification*)notify {
|
| + [self layoutTabsFast];
|
| +}
|
| +
|
| @end
|
|
|