Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: chrome/browser/cocoa/tab_strip_controller.mm

Issue 155758: "Prepatch" for issue 13713 (resize tabstrip upon resizing window on... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/cocoa/tab_strip_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/cocoa/tab_strip_controller.h" 5 #import "chrome/browser/cocoa/tab_strip_controller.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/mac_util.h" 8 #include "base/mac_util.h"
9 #include "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #include "chrome/app/chrome_dll_resource.h" 10 #include "chrome/app/chrome_dll_resource.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 DCHECK([newTabButton_ isKindOfClass:[NSButton class]]); 59 DCHECK([newTabButton_ isKindOfClass:[NSButton class]]);
60 [newTabButton_ setTarget:nil]; 60 [newTabButton_ setTarget:nil];
61 [newTabButton_ setAction:@selector(commandDispatch:)]; 61 [newTabButton_ setAction:@selector(commandDispatch:)];
62 [newTabButton_ setTag:IDC_NEW_TAB]; 62 [newTabButton_ setTag:IDC_NEW_TAB];
63 targetFrames_.reset([[NSMutableDictionary alloc] init]); 63 targetFrames_.reset([[NSMutableDictionary alloc] init]);
64 [tabView_ setWantsLayer:YES]; 64 [tabView_ setWantsLayer:YES];
65 dragBlockingView_.reset([[TabStripControllerDragBlockingView alloc] 65 dragBlockingView_.reset([[TabStripControllerDragBlockingView alloc]
66 initWithFrame:NSZeroRect]); 66 initWithFrame:NSZeroRect]);
67 [view addSubview:dragBlockingView_]; 67 [view addSubview:dragBlockingView_];
68 newTabTargetFrame_ = NSMakeRect(0, 0, 0, 0); 68 newTabTargetFrame_ = NSMakeRect(0, 0, 0, 0);
69
70 // Make sure our TabStripView posts frame change notifications, and
71 // register for them.
72 [tabView_ setPostsFrameChangedNotifications:YES];
73 [[NSNotificationCenter defaultCenter] addObserver:self
74 selector:@selector(tabViewFrameChanged:)
75 name:NSViewFrameDidChangeNotification
76 object:tabView_];
69 } 77 }
70 return self; 78 return self;
71 } 79 }
72 80
73 + (CGFloat)defaultTabHeight { 81 + (CGFloat)defaultTabHeight {
74 return 24.0; 82 return 24.0;
75 } 83 }
76 84
77 // Finds the associated TabContentsController at the given |index| and swaps 85 // Finds the associated TabContentsController at the given |index| and swaps
78 // out the sole child of the contentArea to display its contents. 86 // out the sole child of the contentArea to display its contents.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 201
194 // Lay out all tabs in the order of their TabContentsControllers, which matches 202 // Lay out all tabs in the order of their TabContentsControllers, which matches
195 // the ordering in the TabStripModel. This call isn't that expensive, though 203 // the ordering in the TabStripModel. This call isn't that expensive, though
196 // it is O(n) in the number of tabs. Tabs will animate to their new position 204 // it is O(n) in the number of tabs. Tabs will animate to their new position
197 // if the window is visible. 205 // if the window is visible.
198 // TODO(pinkerton): Handle drag placeholders via proxy objects, perhaps a 206 // TODO(pinkerton): Handle drag placeholders via proxy objects, perhaps a
199 // subclass of TabContentsController with everything stubbed out or by 207 // subclass of TabContentsController with everything stubbed out or by
200 // abstracting a base class interface. 208 // abstracting a base class interface.
201 // TODO(pinkerton): Note this doesn't do too well when the number of min-sized 209 // TODO(pinkerton): Note this doesn't do too well when the number of min-sized
202 // tabs would cause an overflow. 210 // tabs would cause an overflow.
203 - (void)layoutTabs { 211 - (void)layoutTabsCurrent {
204 const float kIndentLeavingSpaceForControls = 64.0; 212 const float kIndentLeavingSpaceForControls = 64.0;
205 const float kTabOverlap = 20.0; 213 const float kTabOverlap = 20.0;
206 const float kNewTabButtonOffset = 8.0; 214 const float kNewTabButtonOffset = 8.0;
207 const float kMaxTabWidth = [TabController maxTabWidth]; 215 const float kMaxTabWidth = [TabController maxTabWidth];
208 const float kMinTabWidth = [TabController minTabWidth]; 216 const float kMinTabWidth = [TabController minTabWidth];
209 const float kMinSelectedTabWidth = [TabController minSelectedTabWidth]; 217 const float kMinSelectedTabWidth = [TabController minSelectedTabWidth];
210 218
211 NSRect enclosingRect = NSZeroRect; 219 NSRect enclosingRect = NSZeroRect;
212 [NSAnimationContext beginGrouping]; 220 [NSAnimationContext beginGrouping];
213 [[NSAnimationContext currentContext] setDuration:0.2]; 221 [[NSAnimationContext currentContext] setDuration:0.2];
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) { 331 if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) {
324 [newTabButton_ setFrame:newTabNewFrame]; 332 [newTabButton_ setFrame:newTabNewFrame];
325 newTabTargetFrame_ = newTabNewFrame; 333 newTabTargetFrame_ = newTabNewFrame;
326 // Move the new tab button into place. 334 // Move the new tab button into place.
327 } 335 }
328 336
329 [NSAnimationContext endGrouping]; 337 [NSAnimationContext endGrouping];
330 [dragBlockingView_ setFrame:enclosingRect]; 338 [dragBlockingView_ setFrame:enclosingRect];
331 } 339 }
332 340
341 //////////////////////////////////////
342 // FIXME -- this is only temporary! //
343 //////////////////////////////////////
344 - (void)layoutTabsVeryTemp {
345 const float kIndentLeavingSpaceForControls = 64.0;
346 const float kTabOverlap = 20.0;
347 const float kNewTabButtonOffset = 8.0;
348 const float kMaxTabWidth = [TabController maxTabWidth];
349 const float kMinTabWidth = [TabController minTabWidth];
350 const float kMinSelectedTabWidth = [TabController minSelectedTabWidth];
351
352 NSRect enclosingRect = NSZeroRect;
353
354 // Compute the base width of tabs given how much size we have available.
355 float availableWidth =
356 NSWidth([tabView_ frame]) - NSWidth([newTabButton_ frame]) -
357 kNewTabButtonOffset - kIndentLeavingSpaceForControls;
358 // Add back in the amount we "get back" from the tabs overlapping.
359 availableWidth += [tabContentsArray_ count] * kTabOverlap;
360 const float baseTabWidth =
361 MAX(MIN(availableWidth / [tabContentsArray_ count],
362 kMaxTabWidth),
363 kMinTabWidth);
364
365 CGFloat minX = NSMinX(placeholderFrame_);
366 BOOL visible = [[tabView_ window] isVisible];
367
368 float offset = kIndentLeavingSpaceForControls;
369 NSUInteger i = 0;
370 NSInteger gap = -1;
371 NSView* previousTab = nil;
372 for (TabController* tab in tabArray_.get()) {
373 BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_];
374 NSRect tabFrame = [[tab view] frame];
375 tabFrame.size.height = [[self class] defaultTabHeight];
376 tabFrame.origin.y = 0;
377 tabFrame.origin.x = offset;
378
379 // If the tab is hidden, we consider it a new tab. We make it visible
380 // and animate it in.
381 BOOL newTab = [[tab view] isHidden];
382 if (newTab) {
383 [[tab view] setHidden:NO];
384 }
385
386 if (isPlaceholder) {
387 // Move the current tab to the correct location intantly.
388 tabFrame.origin.x = placeholderFrame_.origin.x;
389 // TODO(alcor): reenable this
390 //tabFrame.size.height += 10.0 * placeholderStretchiness_;
391 [[tab view] setFrame:tabFrame];
392
393 // Store the frame by identifier to aviod redundant calls to animator.
394 NSValue *identifier = [NSValue valueWithPointer:[tab view]];
395 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
396 forKey:identifier];
397 continue;
398 } else {
399 // If our left edge is to the left of the placeholder's left, but our mid
400 // is to the right of it we should slide over to make space for it.
401 if (placeholderTab_ && gap < 0 && NSMidX(tabFrame) > minX) {
402 gap = i;
403 offset += NSWidth(tabFrame);
404 offset -= kTabOverlap;
405 tabFrame.origin.x = offset;
406 }
407
408 // Animate the tab in by putting it below the horizon.
409 if (newTab && visible) {
410 [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))];
411 }
412
413 // Set the width. Selected tabs are slightly wider when things get
414 // really small and thus we enforce a different minimum width.
415 tabFrame.size.width =
416 [tab selected] ? MAX(baseTabWidth, kMinSelectedTabWidth) :
417 baseTabWidth;
418
419 // Check the frame by identifier to avoid redundant calls to animator.
420 id frameTarget = [tab view];
421 NSValue *identifier = [NSValue valueWithPointer:[tab view]];
422 NSValue *oldTargetValue = [targetFrames_ objectForKey:identifier];
423 if (!oldTargetValue ||
424 !NSEqualRects([oldTargetValue rectValue], tabFrame)) {
425 [frameTarget setFrame:tabFrame];
426 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
427 forKey:identifier];
428 }
429 enclosingRect = NSUnionRect(tabFrame, enclosingRect);
430 }
431
432 // Ensure the current tab is "below" the tab before it in z-order so that
433 // all the tab overlaps are consistent. The selected tab is always the
434 // frontmost, but it's already been made frontmost when the tab was selected
435 // so we don't need to do anything about it here. It will get put back into
436 // place when another tab is selected.
437 if (![tab selected]) {
438 [tabView_ addSubview:[tab view]
439 positioned:NSWindowBelow
440 relativeTo:previousTab];
441 }
442 previousTab = [tab view];
443
444 offset += NSWidth(tabFrame);
445 offset -= kTabOverlap;
446 i++;
447 }
448
449 NSRect newTabNewFrame = [newTabButton_ frame];
450 newTabNewFrame.origin =
451 NSMakePoint(MIN(availableWidth, offset + kNewTabButtonOffset), 0);
452 newTabNewFrame.origin.x = MAX(newTabNewFrame.origin.x,
453 NSMaxX(placeholderFrame_));
454 if (i > 0 && [newTabButton_ isHidden]) {
455 [newTabButton_ setHidden:NO];
456 }
457
458 if (!NSEqualRects(newTabTargetFrame_, newTabNewFrame)) {
459 [newTabButton_ setFrame:newTabNewFrame];
460 newTabTargetFrame_ = newTabNewFrame;
461 // Move the new tab button into place.
462 }
463
464 [dragBlockingView_ setFrame:enclosingRect];
465 }
466
467 // FIXME: Properly produce a unified version of this, which handles both
468 // animated and unanimated cases.
469 - (void)layoutTabsInternal:(BOOL)doAnimate {
470 if (doAnimate)
471 [self layoutTabsCurrent];
472 else
473 [self layoutTabsVeryTemp];
474 }
475
476 // Layout tabs with animation.
477 - (void)layoutTabs {
478 [self layoutTabsInternal:YES];
479 }
480
481 // Layout tabs without animation.
482 - (void)layoutTabsFast {
483 [self layoutTabsInternal:NO];
484 }
485
333 // Handles setting the title of the tab based on the given |contents|. Uses 486 // Handles setting the title of the tab based on the given |contents|. Uses
334 // a canned string if |contents| is NULL. 487 // a canned string if |contents| is NULL.
335 - (void)setTabTitle:(NSViewController*)tab withContents:(TabContents*)contents { 488 - (void)setTabTitle:(NSViewController*)tab withContents:(TabContents*)contents {
336 NSString* titleString = nil; 489 NSString* titleString = nil;
337 if (contents) 490 if (contents)
338 titleString = base::SysUTF16ToNSString(contents->GetTitle()); 491 titleString = base::SysUTF16ToNSString(contents->GetTitle());
339 if (![titleString length]) { 492 if (![titleString length]) {
340 titleString = 493 titleString =
341 base::SysWideToNSString( 494 base::SysWideToNSString(
342 l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED)); 495 l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED));
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 // inherit the current tab's group. 772 // inherit the current tab's group.
620 tabModel_->InsertTabContentsAt(index, contents, true, false); 773 tabModel_->InsertTabContentsAt(index, contents, true, false);
621 } 774 }
622 775
623 - (void)userChangedTheme { 776 - (void)userChangedTheme {
624 for (TabController* tab in tabArray_.get()) { 777 for (TabController* tab in tabArray_.get()) {
625 [[tab view] setNeedsDisplay:YES]; 778 [[tab view] setNeedsDisplay:YES];
626 } 779 }
627 } 780 }
628 781
782 // Called when our TabStripView's frame changes size (i.e., on window resize).
783 // Since resizes are tracked (and yield many events), we need to layout the
784 // tabs quickly.
785 - (void)tabViewFrameChanged:(NSNotification*)notify {
786 [self layoutTabsFast];
787 }
788
629 @end 789 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/tab_strip_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698