| OLD | NEW |
| 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 <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
| 10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 } | 89 } |
| 90 @end | 90 @end |
| 91 | 91 |
| 92 @interface TabStripController(Private) | 92 @interface TabStripController(Private) |
| 93 - (void)installTrackingArea; | 93 - (void)installTrackingArea; |
| 94 - (void)addSubviewToPermanentList:(NSView*)aView; | 94 - (void)addSubviewToPermanentList:(NSView*)aView; |
| 95 - (void)regenerateSubviewList; | 95 - (void)regenerateSubviewList; |
| 96 - (NSInteger)indexForContentsView:(NSView*)view; | 96 - (NSInteger)indexForContentsView:(NSView*)view; |
| 97 - (void)updateFavIconForContents:(TabContents*)contents | 97 - (void)updateFavIconForContents:(TabContents*)contents |
| 98 atIndex:(NSInteger)index; | 98 atIndex:(NSInteger)index; |
| 99 - (void)layoutTabsWithAnimation:(BOOL)animate |
| 100 regenerateSubviews:(BOOL)doUpdate; |
| 99 @end | 101 @end |
| 100 | 102 |
| 101 @implementation TabStripController | 103 @implementation TabStripController |
| 102 | 104 |
| 103 - (id)initWithView:(TabStripView*)view | 105 - (id)initWithView:(TabStripView*)view |
| 104 switchView:(NSView*)switchView | 106 switchView:(NSView*)switchView |
| 105 browser:(Browser*)browser { | 107 browser:(Browser*)browser { |
| 106 DCHECK(view && switchView && browser); | 108 DCHECK(view && switchView && browser); |
| 107 if ((self = [super init])) { | 109 if ((self = [super init])) { |
| 108 tabView_.reset([view retain]); | 110 tabView_.reset([view retain]); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 int index = [self indexForTabView:[controller view]]; | 331 int index = [self indexForTabView:[controller view]]; |
| 330 return tabModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO; | 332 return tabModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO; |
| 331 } | 333 } |
| 332 | 334 |
| 333 - (void)insertPlaceholderForTab:(TabView*)tab | 335 - (void)insertPlaceholderForTab:(TabView*)tab |
| 334 frame:(NSRect)frame | 336 frame:(NSRect)frame |
| 335 yStretchiness:(CGFloat)yStretchiness { | 337 yStretchiness:(CGFloat)yStretchiness { |
| 336 placeholderTab_ = tab; | 338 placeholderTab_ = tab; |
| 337 placeholderFrame_ = frame; | 339 placeholderFrame_ = frame; |
| 338 placeholderStretchiness_ = yStretchiness; | 340 placeholderStretchiness_ = yStretchiness; |
| 339 [self layoutTabs]; | 341 [self layoutTabsWithAnimation:YES regenerateSubviews:NO]; |
| 340 } | 342 } |
| 341 | 343 |
| 342 - (BOOL)isTabFullyVisible:(TabView*)tab { | 344 - (BOOL)isTabFullyVisible:(TabView*)tab { |
| 343 NSRect frame = [tab frame]; | 345 NSRect frame = [tab frame]; |
| 344 return NSMinX(frame) >= kIndentLeavingSpaceForControls && | 346 return NSMinX(frame) >= kIndentLeavingSpaceForControls && |
| 345 NSMaxX(frame) <= NSMaxX([tabView_ frame]); | 347 NSMaxX(frame) <= NSMaxX([tabView_ frame]); |
| 346 } | 348 } |
| 347 | 349 |
| 348 - (void)showNewTabButton:(BOOL)show { | 350 - (void)showNewTabButton:(BOOL)show { |
| 349 forceNewTabButtonHidden_ = show ? NO : YES; | 351 forceNewTabButtonHidden_ = show ? NO : YES; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 const float baseTabWidth = | 403 const float baseTabWidth = |
| 402 MAX(MIN(availableWidth / [tabContentsArray_ count], | 404 MAX(MIN(availableWidth / [tabContentsArray_ count], |
| 403 kMaxTabWidth), | 405 kMaxTabWidth), |
| 404 kMinTabWidth); | 406 kMinTabWidth); |
| 405 | 407 |
| 406 CGFloat minX = NSMinX(placeholderFrame_); | 408 CGFloat minX = NSMinX(placeholderFrame_); |
| 407 BOOL visible = [[tabView_ window] isVisible]; | 409 BOOL visible = [[tabView_ window] isVisible]; |
| 408 | 410 |
| 409 float offset = kIndentLeavingSpaceForControls; | 411 float offset = kIndentLeavingSpaceForControls; |
| 410 NSUInteger i = 0; | 412 NSUInteger i = 0; |
| 411 NSInteger gap = -1; | 413 bool hasPlaceholderGap = false; |
| 412 for (TabController* tab in tabArray_.get()) { | 414 for (TabController* tab in tabArray_.get()) { |
| 413 BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_]; | 415 BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_]; |
| 414 NSRect tabFrame = [[tab view] frame]; | 416 NSRect tabFrame = [[tab view] frame]; |
| 415 tabFrame.size.height = [[self class] defaultTabHeight] + 1; | 417 tabFrame.size.height = [[self class] defaultTabHeight] + 1; |
| 416 tabFrame.origin.y = 0; | 418 tabFrame.origin.y = 0; |
| 417 tabFrame.origin.x = offset; | 419 tabFrame.origin.x = offset; |
| 418 | 420 |
| 419 // If the tab is hidden, we consider it a new tab. We make it visible | 421 // If the tab is hidden, we consider it a new tab. We make it visible |
| 420 // and animate it in. | 422 // and animate it in. |
| 421 BOOL newTab = [[tab view] isHidden]; | 423 BOOL newTab = [[tab view] isHidden]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 436 [NSAnimationContext endGrouping]; | 438 [NSAnimationContext endGrouping]; |
| 437 | 439 |
| 438 // Store the frame by identifier to aviod redundant calls to animator. | 440 // Store the frame by identifier to aviod redundant calls to animator. |
| 439 NSValue* identifier = [NSValue valueWithPointer:[tab view]]; | 441 NSValue* identifier = [NSValue valueWithPointer:[tab view]]; |
| 440 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] | 442 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] |
| 441 forKey:identifier]; | 443 forKey:identifier]; |
| 442 continue; | 444 continue; |
| 443 } else { | 445 } else { |
| 444 // If our left edge is to the left of the placeholder's left, but our mid | 446 // If our left edge is to the left of the placeholder's left, but our mid |
| 445 // is to the right of it we should slide over to make space for it. | 447 // is to the right of it we should slide over to make space for it. |
| 446 if (placeholderTab_ && gap < 0 && NSMidX(tabFrame) > minX) { | 448 if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) { |
| 447 gap = i; | 449 hasPlaceholderGap = true; |
| 448 offset += NSWidth(tabFrame); | 450 offset += NSWidth(placeholderFrame_); |
| 449 offset -= kTabOverlap; | 451 offset -= kTabOverlap; |
| 450 tabFrame.origin.x = offset; | 452 tabFrame.origin.x = offset; |
| 451 } | 453 } |
| 452 | 454 |
| 453 // Set the width. Selected tabs are slightly wider when things get | 455 // Set the width. Selected tabs are slightly wider when things get |
| 454 // really small and thus we enforce a different minimum width. | 456 // really small and thus we enforce a different minimum width. |
| 455 tabFrame.size.width = | 457 tabFrame.size.width = |
| 456 [tab selected] ? MAX(baseTabWidth, kMinSelectedTabWidth) : | 458 [tab selected] ? MAX(baseTabWidth, kMinSelectedTabWidth) : |
| 457 baseTabWidth; | 459 baseTabWidth; |
| 458 | 460 |
| 459 // Animate a new tab in by putting it below the horizon. | 461 // Animate a new tab in by putting it below the horizon unless |
| 462 // told to put it in a specific location (ie, from a drop). |
| 460 if (newTab && visible && animate) { | 463 if (newTab && visible && animate) { |
| 461 [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))]; | 464 if (NSEqualRects(droppedTabFrame_, NSZeroRect)) { |
| 465 [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))]; |
| 466 } else { |
| 467 [[tab view] setFrame:droppedTabFrame_]; |
| 468 droppedTabFrame_ = NSZeroRect; |
| 469 } |
| 462 } | 470 } |
| 463 | 471 |
| 464 // Check the frame by identifier to avoid redundant calls to animator. | 472 // Check the frame by identifier to avoid redundant calls to animator. |
| 465 id frameTarget = visible && animate ? [[tab view] animator] : [tab view]; | 473 id frameTarget = visible && animate ? [[tab view] animator] : [tab view]; |
| 466 NSValue* identifier = [NSValue valueWithPointer:[tab view]]; | 474 NSValue* identifier = [NSValue valueWithPointer:[tab view]]; |
| 467 NSValue* oldTargetValue = [targetFrames_ objectForKey:identifier]; | 475 NSValue* oldTargetValue = [targetFrames_ objectForKey:identifier]; |
| 468 if (!oldTargetValue || | 476 if (!oldTargetValue || |
| 469 !NSEqualRects([oldTargetValue rectValue], tabFrame)) { | 477 !NSEqualRects([oldTargetValue rectValue], tabFrame)) { |
| 470 [frameTarget setFrame:tabFrame]; | 478 [frameTarget setFrame:tabFrame]; |
| 471 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] | 479 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // Move the given tab at index |from| in this window to the location of the | 859 // Move the given tab at index |from| in this window to the location of the |
| 852 // current placeholder. | 860 // current placeholder. |
| 853 - (void)moveTabFromIndex:(NSInteger)from { | 861 - (void)moveTabFromIndex:(NSInteger)from { |
| 854 int toIndex = [self indexOfPlaceholder]; | 862 int toIndex = [self indexOfPlaceholder]; |
| 855 tabModel_->MoveTabContentsAt(from, toIndex, true); | 863 tabModel_->MoveTabContentsAt(from, toIndex, true); |
| 856 } | 864 } |
| 857 | 865 |
| 858 // Drop a given TabContents at the location of the current placeholder. If there | 866 // Drop a given TabContents at the location of the current placeholder. If there |
| 859 // is no placeholder, it will go at the end. Used when dragging from another | 867 // is no placeholder, it will go at the end. Used when dragging from another |
| 860 // window when we don't have access to the TabContents as part of our strip. | 868 // window when we don't have access to the TabContents as part of our strip. |
| 861 - (void)dropTabContents:(TabContents*)contents { | 869 // |frame| is in the coordinate system of the tab strip view and represents |
| 870 // where the user dropped the new tab so it can be animated into its correct |
| 871 // location when the tab is added to the model. |
| 872 - (void)dropTabContents:(TabContents*)contents withFrame:(NSRect)frame { |
| 862 int index = [self indexOfPlaceholder]; | 873 int index = [self indexOfPlaceholder]; |
| 863 | 874 |
| 875 // Mark that the new tab being created should start at |frame|. It will be |
| 876 // reset as soon as the tab has been positioned. |
| 877 droppedTabFrame_ = frame; |
| 878 |
| 864 // Insert it into this tab strip. We want it in the foreground and to not | 879 // Insert it into this tab strip. We want it in the foreground and to not |
| 865 // inherit the current tab's group. | 880 // inherit the current tab's group. |
| 866 tabModel_->InsertTabContentsAt(index, contents, true, false); | 881 tabModel_->InsertTabContentsAt(index, contents, true, false); |
| 867 } | 882 } |
| 868 | 883 |
| 869 // Called when the tab strip view changes size. As we only registered for | 884 // Called when the tab strip view changes size. As we only registered for |
| 870 // changes on our view, we know it's only for our view. Layout w/out | 885 // changes on our view, we know it's only for our view. Layout w/out |
| 871 // animations since they are blocked by the resize nested runloop. We need | 886 // animations since they are blocked by the resize nested runloop. We need |
| 872 // the views to adjust immediately. Neither the tabs nor their z-order are | 887 // the views to adjust immediately. Neither the tabs nor their z-order are |
| 873 // changed, so we don't need to update the subviews. | 888 // changed, so we don't need to update the subviews. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 BrowserWindowController* controller = | 1023 BrowserWindowController* controller = |
| 1009 (BrowserWindowController*)[[switchView_ window] windowController]; | 1024 (BrowserWindowController*)[[switchView_ window] windowController]; |
| 1010 DCHECK(index >= 0); | 1025 DCHECK(index >= 0); |
| 1011 if (index >= 0) { | 1026 if (index >= 0) { |
| 1012 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; | 1027 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; |
| 1013 } | 1028 } |
| 1014 } | 1029 } |
| 1015 | 1030 |
| 1016 | 1031 |
| 1017 @end | 1032 @end |
| OLD | NEW |