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 |