| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #import <QuartzCore/QuartzCore.h> | 7 #import <QuartzCore/QuartzCore.h> |
| 8 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 - (void)regenerateSubviewList; | 116 - (void)regenerateSubviewList; |
| 117 - (NSInteger)indexForContentsView:(NSView*)view; | 117 - (NSInteger)indexForContentsView:(NSView*)view; |
| 118 - (void)updateFavIconForContents:(TabContents*)contents | 118 - (void)updateFavIconForContents:(TabContents*)contents |
| 119 atIndex:(NSInteger)modelIndex; | 119 atIndex:(NSInteger)modelIndex; |
| 120 - (void)layoutTabsWithAnimation:(BOOL)animate | 120 - (void)layoutTabsWithAnimation:(BOOL)animate |
| 121 regenerateSubviews:(BOOL)doUpdate; | 121 regenerateSubviews:(BOOL)doUpdate; |
| 122 - (void)animationDidStopForController:(TabController*)controller | 122 - (void)animationDidStopForController:(TabController*)controller |
| 123 finished:(BOOL)finished; | 123 finished:(BOOL)finished; |
| 124 - (NSInteger)indexFromModelIndex:(NSInteger)index; | 124 - (NSInteger)indexFromModelIndex:(NSInteger)index; |
| 125 - (NSInteger)numberOfOpenTabs; | 125 - (NSInteger)numberOfOpenTabs; |
| 126 - (NSInteger)numberOfOpenPinnedTabs; | 126 - (NSInteger)numberOfOpenMiniTabs; |
| 127 - (NSInteger)numberOfOpenUnpinnedTabs; | 127 - (NSInteger)numberOfOpenNonMiniTabs; |
| 128 - (void)mouseMoved:(NSEvent*)event; | 128 - (void)mouseMoved:(NSEvent*)event; |
| 129 - (void)setTabTrackingAreasEnabled:(BOOL)enabled; | 129 - (void)setTabTrackingAreasEnabled:(BOOL)enabled; |
| 130 - (void)droppingURLsAt:(NSPoint)point | 130 - (void)droppingURLsAt:(NSPoint)point |
| 131 givesIndex:(NSInteger*)index | 131 givesIndex:(NSInteger*)index |
| 132 disposition:(WindowOpenDisposition*)disposition; | 132 disposition:(WindowOpenDisposition*)disposition; |
| 133 @end | 133 @end |
| 134 | 134 |
| 135 // A simple view class that prevents the Window Server from dragging the area | 135 // A simple view class that prevents the Window Server from dragging the area |
| 136 // behind tabs. Sometimes core animation confuses it. Unfortunately, it can also | 136 // behind tabs. Sometimes core animation confuses it. Unfortunately, it can also |
| 137 // falsely pick up clicks during rapid tab closure, so we have to account for | 137 // falsely pick up clicks during rapid tab closure, so we have to account for |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 return controller; | 455 return controller; |
| 456 } | 456 } |
| 457 | 457 |
| 458 // (Private) Returns the number of open tabs in the tab strip. This is the | 458 // (Private) Returns the number of open tabs in the tab strip. This is the |
| 459 // number of TabControllers we know about (as there's a 1-to-1 mapping from | 459 // number of TabControllers we know about (as there's a 1-to-1 mapping from |
| 460 // these controllers to a tab) less the number of closing tabs. | 460 // these controllers to a tab) less the number of closing tabs. |
| 461 - (NSInteger)numberOfOpenTabs { | 461 - (NSInteger)numberOfOpenTabs { |
| 462 return static_cast<NSInteger>(tabStripModel_->count()); | 462 return static_cast<NSInteger>(tabStripModel_->count()); |
| 463 } | 463 } |
| 464 | 464 |
| 465 // (Private) Returns the number of open, pinned tabs. | 465 // (Private) Returns the number of open, mini-tabs. |
| 466 - (NSInteger)numberOfOpenPinnedTabs { | 466 - (NSInteger)numberOfOpenMiniTabs { |
| 467 // Ask the model for the number of pinned tabs. Note that tabs which are in | 467 // Ask the model for the number of mini tabs. Note that tabs which are in |
| 468 // the process of closing (i.e., whose controllers are in | 468 // the process of closing (i.e., whose controllers are in |
| 469 // |closingControllers_|) have already been removed from the model. | 469 // |closingControllers_|) have already been removed from the model. |
| 470 // TODO: convert to apps. | 470 return tabStripModel_->IndexOfFirstNonMiniTab(); |
| 471 return 0; | |
| 472 } | 471 } |
| 473 | 472 |
| 474 // (Private) Returns the number of open, unpinned tabs. | 473 // (Private) Returns the number of open, non-mini tabs. |
| 475 - (NSInteger)numberOfOpenUnpinnedTabs { | 474 - (NSInteger)numberOfOpenNonMiniTabs { |
| 476 NSInteger number = [self numberOfOpenTabs] - [self numberOfOpenPinnedTabs]; | 475 NSInteger number = [self numberOfOpenTabs] - [self numberOfOpenMiniTabs]; |
| 477 DCHECK_GE(number, 0); | 476 DCHECK_GE(number, 0); |
| 478 return number; | 477 return number; |
| 479 } | 478 } |
| 480 | 479 |
| 481 // Given an index into the tab model, returns the index into the tab controller | 480 // Given an index into the tab model, returns the index into the tab controller |
| 482 // or tab contents controller array accounting for tabs that are currently | 481 // or tab contents controller array accounting for tabs that are currently |
| 483 // closing. For example, if there are two tabs in the process of closing before | 482 // closing. For example, if there are two tabs in the process of closing before |
| 484 // |index|, this returns |index| + 2. If there are no closing tabs, this will | 483 // |index|, this returns |index| + 2. If there are no closing tabs, this will |
| 485 // return |index|. | 484 // return |index|. |
| 486 - (NSInteger)indexFromModelIndex:(NSInteger)index { | 485 - (NSInteger)indexFromModelIndex:(NSInteger)index { |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 // tabs would cause an overflow. http://crbug.com/188 | 646 // tabs would cause an overflow. http://crbug.com/188 |
| 648 - (void)layoutTabsWithAnimation:(BOOL)animate | 647 - (void)layoutTabsWithAnimation:(BOOL)animate |
| 649 regenerateSubviews:(BOOL)doUpdate { | 648 regenerateSubviews:(BOOL)doUpdate { |
| 650 DCHECK([NSThread isMainThread]); | 649 DCHECK([NSThread isMainThread]); |
| 651 if (![tabArray_ count]) | 650 if (![tabArray_ count]) |
| 652 return; | 651 return; |
| 653 | 652 |
| 654 const CGFloat kMaxTabWidth = [TabController maxTabWidth]; | 653 const CGFloat kMaxTabWidth = [TabController maxTabWidth]; |
| 655 const CGFloat kMinTabWidth = [TabController minTabWidth]; | 654 const CGFloat kMinTabWidth = [TabController minTabWidth]; |
| 656 const CGFloat kMinSelectedTabWidth = [TabController minSelectedTabWidth]; | 655 const CGFloat kMinSelectedTabWidth = [TabController minSelectedTabWidth]; |
| 657 const CGFloat kPinnedTabWidth = [TabController pinnedTabWidth]; | 656 const CGFloat kMiniTabWidth = [TabController miniTabWidth]; |
| 658 | 657 |
| 659 NSRect enclosingRect = NSZeroRect; | 658 NSRect enclosingRect = NSZeroRect; |
| 660 ScopedNSAnimationContextGroup mainAnimationGroup(animate); | 659 ScopedNSAnimationContextGroup mainAnimationGroup(animate); |
| 661 mainAnimationGroup.SetCurrentContextDuration(kAnimationDuration); | 660 mainAnimationGroup.SetCurrentContextDuration(kAnimationDuration); |
| 662 | 661 |
| 663 // Update the current subviews and their z-order if requested. | 662 // Update the current subviews and their z-order if requested. |
| 664 if (doUpdate) | 663 if (doUpdate) |
| 665 [self regenerateSubviewList]; | 664 [self regenerateSubviewList]; |
| 666 | 665 |
| 667 // Compute the base width of tabs given how much room we're allowed. Note that | 666 // Compute the base width of tabs given how much room we're allowed. Note that |
| 668 // pinned tabs have a fixed width. We may not be able to use the entire width | 667 // mini-tabs have a fixed width. We may not be able to use the entire width |
| 669 // if the user is quickly closing tabs. This may be negative, but that's okay | 668 // if the user is quickly closing tabs. This may be negative, but that's okay |
| 670 // (taken care of by |MAX()| when calculating tab sizes). | 669 // (taken care of by |MAX()| when calculating tab sizes). |
| 671 CGFloat availableWidth = 0; | 670 CGFloat availableWidth = 0; |
| 672 if ([self inRapidClosureMode]) { | 671 if ([self inRapidClosureMode]) { |
| 673 availableWidth = availableResizeWidth_; | 672 availableWidth = availableResizeWidth_; |
| 674 } else { | 673 } else { |
| 675 availableWidth = NSWidth([tabStripView_ frame]); | 674 availableWidth = NSWidth([tabStripView_ frame]); |
| 676 // Account for the new tab button and the incognito badge. | 675 // Account for the new tab button and the incognito badge. |
| 677 availableWidth -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset; | 676 availableWidth -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset; |
| 678 if (browser_->profile()->IsOffTheRecord()) | 677 if (browser_->profile()->IsOffTheRecord()) |
| 679 availableWidth -= kIncognitoBadgeTabStripShrink; | 678 availableWidth -= kIncognitoBadgeTabStripShrink; |
| 680 } | 679 } |
| 681 availableWidth -= [self indentForControls]; | 680 availableWidth -= [self indentForControls]; |
| 682 | 681 |
| 683 // This may be negative, but that's okay (taken care of by |MAX()| when | 682 // This may be negative, but that's okay (taken care of by |MAX()| when |
| 684 // calculating tab sizes). | 683 // calculating tab sizes). |
| 685 CGFloat availableWidthForUnpinned = availableWidth - | 684 CGFloat availableWidthForNonMini = availableWidth - |
| 686 [self numberOfOpenPinnedTabs] * (kPinnedTabWidth - kTabOverlap); | 685 [self numberOfOpenMiniTabs] * (kMiniTabWidth - kTabOverlap); |
| 687 | 686 |
| 688 // Initialize |unpinnedTabWidth| in case there aren't any unpinned tabs; this | 687 // Initialize |nonMiniTabWidth| in case there aren't any non-mini-tabs; this |
| 689 // value shouldn't actually be used. | 688 // value shouldn't actually be used. |
| 690 CGFloat unpinnedTabWidth = kMaxTabWidth; | 689 CGFloat nonMiniTabWidth = kMaxTabWidth; |
| 691 const NSInteger numberOfOpenUnpinnedTabs = [self numberOfOpenUnpinnedTabs]; | 690 const NSInteger numberOfOpenNonMiniTabs = [self numberOfOpenNonMiniTabs]; |
| 692 if (numberOfOpenUnpinnedTabs) { // Find the width of an unpinned tab. | 691 if (numberOfOpenNonMiniTabs) { // Find the width of a non-mini-tab. |
| 693 // Add in the amount we "get back" from the tabs overlapping. | 692 // Add in the amount we "get back" from the tabs overlapping. |
| 694 availableWidthForUnpinned += (numberOfOpenUnpinnedTabs - 1) * kTabOverlap; | 693 availableWidthForNonMini += (numberOfOpenNonMiniTabs - 1) * kTabOverlap; |
| 695 | 694 |
| 696 // Divide up the space between the unpinned tabs. | 695 // Divide up the space between the non-mini-tabs. |
| 697 unpinnedTabWidth = availableWidthForUnpinned / numberOfOpenUnpinnedTabs; | 696 nonMiniTabWidth = availableWidthForNonMini / numberOfOpenNonMiniTabs; |
| 698 | 697 |
| 699 // Clamp the width between the max and min. | 698 // Clamp the width between the max and min. |
| 700 unpinnedTabWidth = MAX(MIN(unpinnedTabWidth, kMaxTabWidth), kMinTabWidth); | 699 nonMiniTabWidth = MAX(MIN(nonMiniTabWidth, kMaxTabWidth), kMinTabWidth); |
| 701 } | 700 } |
| 702 | 701 |
| 703 const CGFloat minX = NSMinX(placeholderFrame_); | 702 const CGFloat minX = NSMinX(placeholderFrame_); |
| 704 BOOL visible = [[tabStripView_ window] isVisible]; | 703 BOOL visible = [[tabStripView_ window] isVisible]; |
| 705 | 704 |
| 706 CGFloat offset = [self indentForControls]; | 705 CGFloat offset = [self indentForControls]; |
| 707 NSUInteger i = 0; | 706 NSUInteger i = 0; |
| 708 bool hasPlaceholderGap = false; | 707 bool hasPlaceholderGap = false; |
| 709 for (TabController* tab in tabArray_.get()) { | 708 for (TabController* tab in tabArray_.get()) { |
| 710 // Ignore a tab that is going through a close animation. | 709 // Ignore a tab that is going through a close animation. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // to the right of it we should slide over to make space for it. | 745 // to the right of it we should slide over to make space for it. |
| 747 if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) { | 746 if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) { |
| 748 hasPlaceholderGap = true; | 747 hasPlaceholderGap = true; |
| 749 offset += NSWidth(placeholderFrame_); | 748 offset += NSWidth(placeholderFrame_); |
| 750 offset -= kTabOverlap; | 749 offset -= kTabOverlap; |
| 751 tabFrame.origin.x = offset; | 750 tabFrame.origin.x = offset; |
| 752 } | 751 } |
| 753 | 752 |
| 754 // Set the width. Selected tabs are slightly wider when things get really | 753 // Set the width. Selected tabs are slightly wider when things get really |
| 755 // small and thus we enforce a different minimum width. | 754 // small and thus we enforce a different minimum width. |
| 756 tabFrame.size.width = [tab pinned] ? kPinnedTabWidth : unpinnedTabWidth; | 755 tabFrame.size.width = [tab mini] ? kMiniTabWidth : nonMiniTabWidth; |
| 757 if ([tab selected]) | 756 if ([tab selected]) |
| 758 tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth); | 757 tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth); |
| 759 | 758 |
| 760 // Animate a new tab in by putting it below the horizon unless told to put | 759 // Animate a new tab in by putting it below the horizon unless told to put |
| 761 // it in a specific location (i.e., from a drop). | 760 // it in a specific location (i.e., from a drop). |
| 762 if (newTab && visible && animate) { | 761 if (newTab && visible && animate) { |
| 763 if (NSEqualRects(droppedTabFrame_, NSZeroRect)) { | 762 if (NSEqualRects(droppedTabFrame_, NSZeroRect)) { |
| 764 [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))]; | 763 [[tab view] setFrame:NSOffsetRect(tabFrame, 0, -NSHeight(tabFrame))]; |
| 765 } else { | 764 } else { |
| 766 [[tab view] setFrame:droppedTabFrame_]; | 765 [[tab view] setFrame:droppedTabFrame_]; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 // Make a new tab. Load the contents of this tab from the nib and associate | 876 // Make a new tab. Load the contents of this tab from the nib and associate |
| 878 // the new controller with |contents| so it can be looked up later. | 877 // the new controller with |contents| so it can be looked up later. |
| 879 TabContentsController* contentsController = | 878 TabContentsController* contentsController = |
| 880 [[[TabContentsController alloc] initWithNibName:@"TabContents" | 879 [[[TabContentsController alloc] initWithNibName:@"TabContents" |
| 881 contents:contents] | 880 contents:contents] |
| 882 autorelease]; | 881 autorelease]; |
| 883 [tabContentsArray_ insertObject:contentsController atIndex:index]; | 882 [tabContentsArray_ insertObject:contentsController atIndex:index]; |
| 884 | 883 |
| 885 // Make a new tab and add it to the strip. Keep track of its controller. | 884 // Make a new tab and add it to the strip. Keep track of its controller. |
| 886 TabController* newController = [self newTab]; | 885 TabController* newController = [self newTab]; |
| 886 [newController setMini:tabStripModel_->IsMiniTab(modelIndex)]; |
| 887 [tabArray_ insertObject:newController atIndex:index]; | 887 [tabArray_ insertObject:newController atIndex:index]; |
| 888 NSView* newView = [newController view]; | 888 NSView* newView = [newController view]; |
| 889 | 889 |
| 890 // Set the originating frame to just below the strip so that it animates | 890 // Set the originating frame to just below the strip so that it animates |
| 891 // upwards as it's being initially layed out. Oddly, this works while doing | 891 // upwards as it's being initially layed out. Oddly, this works while doing |
| 892 // something similar in |-layoutTabs| confuses the window server. | 892 // something similar in |-layoutTabs| confuses the window server. |
| 893 [newView setFrame:NSOffsetRect([newView frame], | 893 [newView setFrame:NSOffsetRect([newView frame], |
| 894 0, -[[self class] defaultTabHeight])]; | 894 0, -[[self class] defaultTabHeight])]; |
| 895 | 895 |
| 896 [self setTabTitle:newController withContents:contents]; | 896 [self setTabTitle:newController withContents:contents]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 921 | 921 |
| 922 // Called when a notification is received from the model to select a particular | 922 // Called when a notification is received from the model to select a particular |
| 923 // tab. Swaps in the toolbar and content area associated with |newContents|. | 923 // tab. Swaps in the toolbar and content area associated with |newContents|. |
| 924 - (void)selectTabWithContents:(TabContents*)newContents | 924 - (void)selectTabWithContents:(TabContents*)newContents |
| 925 previousContents:(TabContents*)oldContents | 925 previousContents:(TabContents*)oldContents |
| 926 atIndex:(NSInteger)modelIndex | 926 atIndex:(NSInteger)modelIndex |
| 927 userGesture:(bool)wasUserGesture { | 927 userGesture:(bool)wasUserGesture { |
| 928 // Take closing tabs into account. | 928 // Take closing tabs into account. |
| 929 NSInteger index = [self indexFromModelIndex:modelIndex]; | 929 NSInteger index = [self indexFromModelIndex:modelIndex]; |
| 930 | 930 |
| 931 if (oldContents) { |
| 932 int oldModelIndex = |
| 933 browser_->GetIndexOfController(&(oldContents->controller())); |
| 934 if (oldModelIndex != -1) { // When closing a tab, the old tab may be gone. |
| 935 NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex]; |
| 936 TabContentsController* oldController = |
| 937 [tabContentsArray_ objectAtIndex:oldIndex]; |
| 938 [oldController willBecomeUnselectedTab]; |
| 939 oldContents->view()->StoreFocus(); |
| 940 oldContents->WasHidden(); |
| 941 // If the selection changed because the tab was made phantom, update the |
| 942 // Cocoa side of the state. |
| 943 TabController* tabController = [tabArray_ objectAtIndex:oldIndex]; |
| 944 [tabController setPhantom:tabStripModel_->IsPhantomTab(oldModelIndex)]; |
| 945 } |
| 946 } |
| 947 |
| 931 // De-select all other tabs and select the new tab. | 948 // De-select all other tabs and select the new tab. |
| 932 int i = 0; | 949 int i = 0; |
| 933 for (TabController* current in tabArray_.get()) { | 950 for (TabController* current in tabArray_.get()) { |
| 934 [current setSelected:(i == index) ? YES : NO]; | 951 [current setSelected:(i == index) ? YES : NO]; |
| 935 ++i; | 952 ++i; |
| 936 } | 953 } |
| 937 | 954 |
| 938 // Tell the new tab contents it is about to become the selected tab. Here it | 955 // Tell the new tab contents it is about to become the selected tab. Here it |
| 939 // can do things like make sure the toolbar is up to date. | 956 // can do things like make sure the toolbar is up to date. |
| 940 TabContentsController* newController = | 957 TabContentsController* newController = |
| 941 [tabContentsArray_ objectAtIndex:index]; | 958 [tabContentsArray_ objectAtIndex:index]; |
| 942 [newController willBecomeSelectedTab]; | 959 [newController willBecomeSelectedTab]; |
| 943 | 960 |
| 944 // Relayout for new tabs and to let the selected tab grow to be larger in | 961 // Relayout for new tabs and to let the selected tab grow to be larger in |
| 945 // size than surrounding tabs if the user has many. This also raises the | 962 // size than surrounding tabs if the user has many. This also raises the |
| 946 // selected tab to the top. | 963 // selected tab to the top. |
| 947 [self layoutTabs]; | 964 [self layoutTabs]; |
| 948 | 965 |
| 949 if (oldContents) { | |
| 950 int oldModelIndex = | |
| 951 browser_->GetIndexOfController(&(oldContents->controller())); | |
| 952 if (oldModelIndex != -1) { // When closing a tab, the old tab may be gone. | |
| 953 NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex]; | |
| 954 TabContentsController* oldController = | |
| 955 [tabContentsArray_ objectAtIndex:oldIndex]; | |
| 956 [oldController willBecomeUnselectedTab]; | |
| 957 oldContents->view()->StoreFocus(); | |
| 958 oldContents->WasHidden(); | |
| 959 } | |
| 960 } | |
| 961 | |
| 962 // Swap in the contents for the new tab. | 966 // Swap in the contents for the new tab. |
| 963 [self swapInTabAtIndex:modelIndex]; | 967 [self swapInTabAtIndex:modelIndex]; |
| 964 [self updateDevToolsForContents:newContents]; | 968 [self updateDevToolsForContents:newContents]; |
| 965 | 969 |
| 966 if (newContents) { | 970 if (newContents) { |
| 967 newContents->DidBecomeSelected(); | 971 newContents->DidBecomeSelected(); |
| 968 newContents->view()->RestoreFocus(); | 972 newContents->view()->RestoreFocus(); |
| 969 | 973 |
| 970 if (newContents->find_ui_active()) | 974 if (newContents->find_ui_active()) |
| 971 browser_->GetFindBarController()->find_bar()->SetFocusAndSelection(); | 975 browser_->GetFindBarController()->find_bar()->SetFocusAndSelection(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 retain]; | 1121 retain]; |
| 1118 static NSImage* sadFaviconImage = | 1122 static NSImage* sadFaviconImage = |
| 1119 [ResourceBundle::GetSharedInstance().GetNSImageNamed(IDR_SAD_FAVICON) | 1123 [ResourceBundle::GetSharedInstance().GetNSImageNamed(IDR_SAD_FAVICON) |
| 1120 retain]; | 1124 retain]; |
| 1121 | 1125 |
| 1122 // Take closing tabs into account. | 1126 // Take closing tabs into account. |
| 1123 NSInteger index = [self indexFromModelIndex:modelIndex]; | 1127 NSInteger index = [self indexFromModelIndex:modelIndex]; |
| 1124 | 1128 |
| 1125 TabController* tabController = [tabArray_ objectAtIndex:index]; | 1129 TabController* tabController = [tabArray_ objectAtIndex:index]; |
| 1126 | 1130 |
| 1131 // Since the tab is loading, it cannot be phantom any more. |
| 1132 if ([tabController phantom]) { |
| 1133 [tabController setPhantom:NO]; |
| 1134 [[tabController view] setNeedsDisplay:YES]; |
| 1135 } |
| 1136 |
| 1127 bool oldHasIcon = [tabController iconView] != nil; | 1137 bool oldHasIcon = [tabController iconView] != nil; |
| 1128 bool newHasIcon = contents->ShouldDisplayFavIcon() || | 1138 bool newHasIcon = contents->ShouldDisplayFavIcon() || |
| 1129 tabStripModel_->IsTabPinned(modelIndex); // always show icon if pinned | 1139 tabStripModel_->IsMiniTab(modelIndex); // Always show icon if mini. |
| 1130 | 1140 |
| 1131 TabLoadingState oldState = [tabController loadingState]; | 1141 TabLoadingState oldState = [tabController loadingState]; |
| 1132 TabLoadingState newState = kTabDone; | 1142 TabLoadingState newState = kTabDone; |
| 1133 NSImage* throbberImage = nil; | 1143 NSImage* throbberImage = nil; |
| 1134 if (contents->is_crashed()) { | 1144 if (contents->is_crashed()) { |
| 1135 newState = kTabCrashed; | 1145 newState = kTabCrashed; |
| 1136 newHasIcon = true; | 1146 newHasIcon = true; |
| 1137 } else if (contents->waiting_for_response()) { | 1147 } else if (contents->waiting_for_response()) { |
| 1138 newState = kTabWaiting; | 1148 newState = kTabWaiting; |
| 1139 throbberImage = throbberWaitingImage; | 1149 throbberImage = throbberWaitingImage; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 changeType:(TabStripModelObserver::TabChangeType)change { | 1190 changeType:(TabStripModelObserver::TabChangeType)change { |
| 1181 // Take closing tabs into account. | 1191 // Take closing tabs into account. |
| 1182 NSInteger index = [self indexFromModelIndex:modelIndex]; | 1192 NSInteger index = [self indexFromModelIndex:modelIndex]; |
| 1183 | 1193 |
| 1184 if (change == TabStripModelObserver::TITLE_NOT_LOADING) { | 1194 if (change == TabStripModelObserver::TITLE_NOT_LOADING) { |
| 1185 // TODO(sky): make this work. | 1195 // TODO(sky): make this work. |
| 1186 // We'll receive another notification of the change asynchronously. | 1196 // We'll receive another notification of the change asynchronously. |
| 1187 return; | 1197 return; |
| 1188 } | 1198 } |
| 1189 | 1199 |
| 1200 TabController* tabController = [tabArray_ objectAtIndex:index]; |
| 1201 |
| 1190 if (change != TabStripModelObserver::LOADING_ONLY) | 1202 if (change != TabStripModelObserver::LOADING_ONLY) |
| 1191 [self setTabTitle:[tabArray_ objectAtIndex:index] withContents:contents]; | 1203 [self setTabTitle:tabController withContents:contents]; |
| 1204 |
| 1205 // See if the change was to/from phantom. |
| 1206 bool isPhantom = tabStripModel_->IsPhantomTab(modelIndex); |
| 1207 if (isPhantom != [tabController phantom]) |
| 1208 [tabController setPhantom:isPhantom]; |
| 1192 | 1209 |
| 1193 [self updateFavIconForContents:contents atIndex:modelIndex]; | 1210 [self updateFavIconForContents:contents atIndex:modelIndex]; |
| 1194 | 1211 |
| 1195 TabContentsController* updatedController = | 1212 TabContentsController* updatedController = |
| 1196 [tabContentsArray_ objectAtIndex:index]; | 1213 [tabContentsArray_ objectAtIndex:index]; |
| 1197 [updatedController tabDidChange:contents]; | 1214 [updatedController tabDidChange:contents]; |
| 1198 } | 1215 } |
| 1199 | 1216 |
| 1200 // Called when a tab is moved (usually by drag&drop). Keep our parallel arrays | 1217 // Called when a tab is moved (usually by drag&drop). Keep our parallel arrays |
| 1201 // in sync with the tab strip model. It can also be pinned/unpinned | 1218 // in sync with the tab strip model. It can also be pinned/unpinned |
| 1202 // simultaneously, so we need to take care of that. | 1219 // simultaneously, so we need to take care of that. |
| 1203 - (void)tabMovedWithContents:(TabContents*)contents | 1220 - (void)tabMovedWithContents:(TabContents*)contents |
| 1204 fromIndex:(NSInteger)modelFrom | 1221 fromIndex:(NSInteger)modelFrom |
| 1205 toIndex:(NSInteger)modelTo | 1222 toIndex:(NSInteger)modelTo { |
| 1206 pinnedStateChanged:(BOOL)pinnedChanged { | |
| 1207 // Take closing tabs into account. | 1223 // Take closing tabs into account. |
| 1208 NSInteger from = [self indexFromModelIndex:modelFrom]; | 1224 NSInteger from = [self indexFromModelIndex:modelFrom]; |
| 1209 NSInteger to = [self indexFromModelIndex:modelTo]; | 1225 NSInteger to = [self indexFromModelIndex:modelTo]; |
| 1210 | 1226 |
| 1211 scoped_nsobject<TabContentsController> movedTabContentsController( | 1227 scoped_nsobject<TabContentsController> movedTabContentsController( |
| 1212 [[tabContentsArray_ objectAtIndex:from] retain]); | 1228 [[tabContentsArray_ objectAtIndex:from] retain]); |
| 1213 [tabContentsArray_ removeObjectAtIndex:from]; | 1229 [tabContentsArray_ removeObjectAtIndex:from]; |
| 1214 [tabContentsArray_ insertObject:movedTabContentsController.get() | 1230 [tabContentsArray_ insertObject:movedTabContentsController.get() |
| 1215 atIndex:to]; | 1231 atIndex:to]; |
| 1216 scoped_nsobject<TabController> movedTabController( | 1232 scoped_nsobject<TabController> movedTabController( |
| 1217 [[tabArray_ objectAtIndex:from] retain]); | 1233 [[tabArray_ objectAtIndex:from] retain]); |
| 1218 DCHECK([movedTabController isKindOfClass:[TabController class]]); | 1234 DCHECK([movedTabController isKindOfClass:[TabController class]]); |
| 1219 [tabArray_ removeObjectAtIndex:from]; | 1235 [tabArray_ removeObjectAtIndex:from]; |
| 1220 [tabArray_ insertObject:movedTabController.get() atIndex:to]; | 1236 [tabArray_ insertObject:movedTabController.get() atIndex:to]; |
| 1221 | 1237 |
| 1222 if (pinnedChanged) { | 1238 // The tab moved, which means that the mini-tab state may have changed. |
| 1223 [movedTabController | 1239 if (tabStripModel_->IsMiniTab(modelTo) != [movedTabController mini]) |
| 1224 setPinned:(tabStripModel_->IsTabPinned(modelTo) ? YES : NO)]; | 1240 [self tabMiniStateChangedWithContents:contents atIndex:modelTo]; |
| 1225 [self updateFavIconForContents:contents atIndex:modelTo]; | |
| 1226 } | |
| 1227 | |
| 1228 // TODO(viettrungluu): I don't think this is needed. Investigate. See also | |
| 1229 // |-tabPinnedStateChangedWithContents:...|. | |
| 1230 [self layoutTabs]; | |
| 1231 } | 1241 } |
| 1232 | 1242 |
| 1233 // Called when a tab is pinned or unpinned without moving. | 1243 // Called when a tab is pinned or unpinned without moving. |
| 1234 - (void)tabPinnedStateChangedWithContents:(TabContents*)contents | 1244 - (void)tabMiniStateChangedWithContents:(TabContents*)contents |
| 1235 atIndex:(NSInteger)modelIndex { | 1245 atIndex:(NSInteger)modelIndex { |
| 1236 // Take closing tabs into account. | 1246 // Take closing tabs into account. |
| 1237 NSInteger index = [self indexFromModelIndex:modelIndex]; | 1247 NSInteger index = [self indexFromModelIndex:modelIndex]; |
| 1238 | 1248 |
| 1239 TabController* tabController = [tabArray_ objectAtIndex:index]; | 1249 TabController* tabController = [tabArray_ objectAtIndex:index]; |
| 1240 DCHECK([tabController isKindOfClass:[TabController class]]); | 1250 DCHECK([tabController isKindOfClass:[TabController class]]); |
| 1241 [tabController setPinned: | 1251 [tabController setMini: |
| 1242 (tabStripModel_->IsTabPinned(modelIndex) ? YES : NO)]; | 1252 (tabStripModel_->IsMiniTab(modelIndex) ? YES : NO)]; |
| 1243 [self updateFavIconForContents:contents atIndex:modelIndex]; | 1253 [self updateFavIconForContents:contents atIndex:modelIndex]; |
| 1244 | |
| 1245 // TODO(viettrungluu): I don't think this is needed. Investigate. See also | |
| 1246 // |-tabMovedWithContents:...|. | |
| 1247 [self layoutTabs]; | |
| 1248 } | 1254 } |
| 1249 | 1255 |
| 1250 - (void)setFrameOfSelectedTab:(NSRect)frame { | 1256 - (void)setFrameOfSelectedTab:(NSRect)frame { |
| 1251 NSView* view = [self selectedTabView]; | 1257 NSView* view = [self selectedTabView]; |
| 1252 NSValue* identifier = [NSValue valueWithPointer:view]; | 1258 NSValue* identifier = [NSValue valueWithPointer:view]; |
| 1253 [targetFrames_ setObject:[NSValue valueWithRect:frame] | 1259 [targetFrames_ setObject:[NSValue valueWithRect:frame] |
| 1254 forKey:identifier]; | 1260 forKey:identifier]; |
| 1255 [view setFrame:frame]; | 1261 [view setFrame:frame]; |
| 1256 } | 1262 } |
| 1257 | 1263 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 - (void)moveTabFromIndex:(NSInteger)from { | 1309 - (void)moveTabFromIndex:(NSInteger)from { |
| 1304 int toIndex = [self indexOfPlaceholder]; | 1310 int toIndex = [self indexOfPlaceholder]; |
| 1305 tabStripModel_->MoveTabContentsAt(from, toIndex, true); | 1311 tabStripModel_->MoveTabContentsAt(from, toIndex, true); |
| 1306 } | 1312 } |
| 1307 | 1313 |
| 1308 // Drop a given TabContents at the location of the current placeholder. If there | 1314 // Drop a given TabContents at the location of the current placeholder. If there |
| 1309 // is no placeholder, it will go at the end. Used when dragging from another | 1315 // is no placeholder, it will go at the end. Used when dragging from another |
| 1310 // window when we don't have access to the TabContents as part of our strip. | 1316 // window when we don't have access to the TabContents as part of our strip. |
| 1311 // |frame| is in the coordinate system of the tab strip view and represents | 1317 // |frame| is in the coordinate system of the tab strip view and represents |
| 1312 // where the user dropped the new tab so it can be animated into its correct | 1318 // where the user dropped the new tab so it can be animated into its correct |
| 1313 // location when the tab is added to the model. | 1319 // location when the tab is added to the model. If the tab was pinned in its |
| 1314 - (void)dropTabContents:(TabContents*)contents withFrame:(NSRect)frame { | 1320 // previous window, setting |pinned| to YES will propagate that state to the |
| 1321 // new window. Mini-tabs are either app or pinned tabs; the app state is stored |
| 1322 // by the |contents|, but the |pinned| state is the caller's responsibility. |
| 1323 - (void)dropTabContents:(TabContents*)contents |
| 1324 withFrame:(NSRect)frame |
| 1325 asPinnedTab:(BOOL)pinned { |
| 1315 int modelIndex = [self indexOfPlaceholder]; | 1326 int modelIndex = [self indexOfPlaceholder]; |
| 1316 | 1327 |
| 1317 // Mark that the new tab being created should start at |frame|. It will be | 1328 // Mark that the new tab being created should start at |frame|. It will be |
| 1318 // reset as soon as the tab has been positioned. | 1329 // reset as soon as the tab has been positioned. |
| 1319 droppedTabFrame_ = frame; | 1330 droppedTabFrame_ = frame; |
| 1320 | 1331 |
| 1321 // Insert it into this tab strip. We want it in the foreground and to not | 1332 // Insert it into this tab strip. We want it in the foreground and to not |
| 1322 // inherit the current tab's group. | 1333 // inherit the current tab's group. |
| 1323 tabStripModel_->InsertTabContentsAt(modelIndex, contents, true, false); | 1334 tabStripModel_->InsertTabContentsAt(modelIndex, contents, true, false, |
| 1324 | 1335 pinned); |
| 1325 // Take closing tabs into account. | |
| 1326 NSInteger index = [self indexFromModelIndex:modelIndex]; | |
| 1327 | |
| 1328 // The tab's pinned status may have changed. | |
| 1329 // TODO(viettrungluu): Improve the behaviour for drops at the dividing point | |
| 1330 // between pinned and unpinned tabs. | |
| 1331 TabController* tabController = [tabArray_ objectAtIndex:index]; | |
| 1332 DCHECK([tabController isKindOfClass:[TabController class]]); | |
| 1333 [tabController setPinned: | |
| 1334 (tabStripModel_->IsTabPinned(modelIndex) ? YES : NO)]; | |
| 1335 [self updateFavIconForContents:contents atIndex:modelIndex]; | |
| 1336 } | 1336 } |
| 1337 | 1337 |
| 1338 // Called when the tab strip view changes size. As we only registered for | 1338 // Called when the tab strip view changes size. As we only registered for |
| 1339 // changes on our view, we know it's only for our view. Layout w/out | 1339 // changes on our view, we know it's only for our view. Layout w/out |
| 1340 // animations since they are blocked by the resize nested runloop. We need | 1340 // animations since they are blocked by the resize nested runloop. We need |
| 1341 // the views to adjust immediately. Neither the tabs nor their z-order are | 1341 // the views to adjust immediately. Neither the tabs nor their z-order are |
| 1342 // changed, so we don't need to update the subviews. | 1342 // changed, so we don't need to update the subviews. |
| 1343 - (void)tabViewFrameChanged:(NSNotification*)info { | 1343 - (void)tabViewFrameChanged:(NSNotification*)info { |
| 1344 [self layoutTabsWithAnimation:NO regenerateSubviews:NO]; | 1344 [self layoutTabsWithAnimation:NO regenerateSubviews:NO]; |
| 1345 } | 1345 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 return; | 1730 return; |
| 1731 | 1731 |
| 1732 TabContentsController* tabController = | 1732 TabContentsController* tabController = |
| 1733 [tabContentsArray_ objectAtIndex:index]; | 1733 [tabContentsArray_ objectAtIndex:index]; |
| 1734 TabContents* devtoolsContents = contents ? | 1734 TabContents* devtoolsContents = contents ? |
| 1735 DevToolsWindow::GetDevToolsContents(contents) : NULL; | 1735 DevToolsWindow::GetDevToolsContents(contents) : NULL; |
| 1736 [tabController showDevToolsContents:devtoolsContents]; | 1736 [tabController showDevToolsContents:devtoolsContents]; |
| 1737 } | 1737 } |
| 1738 | 1738 |
| 1739 @end | 1739 @end |
| OLD | NEW |