Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/ui/cocoa/tabs/tab_strip_controller.h" | 5 #import "chrome/browser/ui/cocoa/tabs/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> |
| 11 | 11 |
| 12 #include "app/mac/nsimage_cache.h" | 12 #include "app/mac/nsimage_cache.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/mac/mac_util.h" | 14 #include "base/mac/mac_util.h" |
| 15 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
| 16 #include "chrome/app/chrome_command_ids.h" | 16 #include "chrome/app/chrome_command_ids.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete.h" | 17 #include "chrome/browser/autocomplete/autocomplete.h" |
| 18 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 18 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
| 19 #include "chrome/browser/autocomplete/autocomplete_match.h" | 19 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 20 #include "chrome/browser/extensions/extension_tab_helper.h" | 20 #include "chrome/browser/extensions/extension_tab_helper.h" |
| 21 #include "chrome/browser/favicon_tab_helper.h" | 21 #include "chrome/browser/favicon_tab_helper.h" |
| 22 #include "chrome/browser/metrics/user_metrics.h" | 22 #include "chrome/browser/metrics/user_metrics.h" |
| 23 #include "chrome/browser/prefs/pref_service.h" | 23 #include "chrome/browser/prefs/pref_service.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/debugger/devtools_window.h" | 25 #include "chrome/browser/debugger/devtools_window.h" |
| 26 #include "chrome/browser/net/url_fixer_upper.h" | 26 #include "chrome/browser/net/url_fixer_upper.h" |
| 27 #include "chrome/browser/sidebar/sidebar_container.h" | 27 #include "chrome/browser/sidebar/sidebar_container.h" |
| 28 #include "chrome/browser/sidebar/sidebar_manager.h" | 28 #include "chrome/browser/sidebar/sidebar_manager.h" |
| 29 #include "chrome/browser/tabs/tab_strip_model.h" | 29 #include "chrome/browser/tabs/tab_strip_model.h" |
| 30 #include "chrome/browser/tabs/tab_strip_selection_model.h" | |
| 30 #include "chrome/browser/ui/browser.h" | 31 #include "chrome/browser/ui/browser.h" |
| 31 #include "chrome/browser/ui/browser_navigator.h" | 32 #include "chrome/browser/ui/browser_navigator.h" |
| 32 #include "chrome/browser/ui/find_bar/find_tab_helper.h" | 33 #include "chrome/browser/ui/find_bar/find_tab_helper.h" |
| 33 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 34 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 34 #import "chrome/browser/ui/cocoa/constrained_window_mac.h" | 35 #import "chrome/browser/ui/cocoa/constrained_window_mac.h" |
| 35 #import "chrome/browser/ui/cocoa/new_tab_button.h" | 36 #import "chrome/browser/ui/cocoa/new_tab_button.h" |
| 36 #import "chrome/browser/ui/cocoa/profile_menu_button.h" | 37 #import "chrome/browser/ui/cocoa/profile_menu_button.h" |
| 37 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h" | 38 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h" |
| 38 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" | 39 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" |
| 39 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" | 40 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" |
| 40 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" | 41 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" |
| 41 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" | 42 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" |
| 42 #import "chrome/browser/ui/cocoa/tracking_area.h" | 43 #import "chrome/browser/ui/cocoa/tracking_area.h" |
| 43 #include "chrome/browser/ui/find_bar/find_bar.h" | 44 #include "chrome/browser/ui/find_bar/find_bar.h" |
| 44 #include "chrome/browser/ui/find_bar/find_bar_controller.h" | 45 #include "chrome/browser/ui/find_bar/find_bar_controller.h" |
| 45 #include "chrome/browser/ui/title_prefix_matcher.h" | 46 #include "chrome/browser/ui/title_prefix_matcher.h" |
| 46 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 47 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 48 #include "chrome/browser/ui/tabs/tab_menu_model.h" | |
| 47 #include "chrome/common/chrome_switches.h" | 49 #include "chrome/common/chrome_switches.h" |
| 48 #include "chrome/common/pref_names.h" | 50 #include "chrome/common/pref_names.h" |
| 49 #include "content/browser/tab_contents/navigation_controller.h" | 51 #include "content/browser/tab_contents/navigation_controller.h" |
| 50 #include "content/browser/tab_contents/navigation_entry.h" | 52 #include "content/browser/tab_contents/navigation_entry.h" |
| 51 #include "content/browser/tab_contents/tab_contents.h" | 53 #include "content/browser/tab_contents/tab_contents.h" |
| 52 #include "content/browser/tab_contents/tab_contents_view.h" | 54 #include "content/browser/tab_contents/tab_contents_view.h" |
| 53 #include "content/common/notification_service.h" | 55 #include "content/common/notification_service.h" |
| 54 #include "grit/app_resources.h" | 56 #include "grit/app_resources.h" |
| 55 #include "grit/generated_resources.h" | 57 #include "grit/generated_resources.h" |
| 56 #include "grit/theme_resources.h" | 58 #include "grit/theme_resources.h" |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 DCHECK_GE(number, 0); | 617 DCHECK_GE(number, 0); |
| 616 return number; | 618 return number; |
| 617 } | 619 } |
| 618 | 620 |
| 619 // Given an index into the tab model, returns the index into the tab controller | 621 // Given an index into the tab model, returns the index into the tab controller |
| 620 // or tab contents controller array accounting for tabs that are currently | 622 // or tab contents controller array accounting for tabs that are currently |
| 621 // closing. For example, if there are two tabs in the process of closing before | 623 // closing. For example, if there are two tabs in the process of closing before |
| 622 // |index|, this returns |index| + 2. If there are no closing tabs, this will | 624 // |index|, this returns |index| + 2. If there are no closing tabs, this will |
| 623 // return |index|. | 625 // return |index|. |
| 624 - (NSInteger)indexFromModelIndex:(NSInteger)index { | 626 - (NSInteger)indexFromModelIndex:(NSInteger)index { |
| 625 DCHECK(index >= 0); | 627 DCHECK_GE(index, 0); |
| 626 if (index < 0) | 628 if (index < 0) |
| 627 return index; | 629 return index; |
| 628 | 630 |
| 629 NSInteger i = 0; | 631 NSInteger i = 0; |
| 630 for (TabController* controller in tabArray_.get()) { | 632 for (TabController* controller in tabArray_.get()) { |
| 631 if ([closingControllers_ containsObject:controller]) { | 633 if ([closingControllers_ containsObject:controller]) { |
| 632 DCHECK([(TabView*)[controller view] isClosing]); | 634 DCHECK([(TabView*)[controller view] isClosing]); |
| 633 ++index; | 635 ++index; |
| 634 } | 636 } |
| 635 if (i == index) // No need to check anything after, it has no effect. | 637 if (i == index) // No need to check anything after, it has no effect. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 690 | 692 |
| 691 - (NSUInteger)viewsCount { | 693 - (NSUInteger)viewsCount { |
| 692 return [tabArray_ count]; | 694 return [tabArray_ count]; |
| 693 } | 695 } |
| 694 | 696 |
| 695 // Called when the user clicks a tab. Tell the model the selection has changed, | 697 // Called when the user clicks a tab. Tell the model the selection has changed, |
| 696 // which feeds back into us via a notification. | 698 // which feeds back into us via a notification. |
| 697 - (void)selectTab:(id)sender { | 699 - (void)selectTab:(id)sender { |
| 698 DCHECK([sender isKindOfClass:[NSView class]]); | 700 DCHECK([sender isKindOfClass:[NSView class]]); |
| 699 int index = [self modelIndexForTabView:sender]; | 701 int index = [self modelIndexForTabView:sender]; |
| 700 if (tabStripModel_->ContainsIndex(index)) | 702 NSUInteger modifiers = [[NSApp currentEvent] modifierFlags]; |
| 701 tabStripModel_->SelectTabContentsAt(index, true); | 703 if (tabStripModel_->ContainsIndex(index)) { |
| 704 if (modifiers & NSCommandKeyMask && modifiers & NSShiftKeyMask) { | |
| 705 tabStripModel_->AddSelectionFromAnchorTo(index); | |
| 706 } else if (modifiers & NSShiftKeyMask) { | |
| 707 tabStripModel_->ExtendSelectionTo(index); | |
| 708 } else if (modifiers & NSCommandKeyMask) { | |
| 709 tabStripModel_->ToggleSelectionAt(index); | |
| 710 } else if (!tabStripModel_->IsTabSelected(index)) { | |
| 711 tabStripModel_->SelectTabContentsAt(index, true); | |
| 712 } | |
| 713 } | |
| 702 } | 714 } |
| 703 | 715 |
| 704 // Called when the user closes a tab. Asks the model to close the tab. |sender| | 716 // Called when the user closes a tab. Asks the model to close the tab. |sender| |
| 705 // is the TabView that is potentially going away. | 717 // is the TabView that is potentially going away. |
| 706 - (void)closeTab:(id)sender { | 718 - (void)closeTab:(id)sender { |
| 707 DCHECK([sender isKindOfClass:[TabView class]]); | 719 DCHECK([sender isKindOfClass:[TabView class]]); |
| 708 if ([hoveredTab_ isEqual:sender]) { | 720 if ([hoveredTab_ isEqual:sender]) { |
| 709 hoveredTab_ = nil; | 721 hoveredTab_ = nil; |
| 710 } | 722 } |
| 711 | 723 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 // Returns YES if the specificed command should be enabled for the given | 776 // Returns YES if the specificed command should be enabled for the given |
| 765 // controller. | 777 // controller. |
| 766 - (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command | 778 - (BOOL)isCommandEnabled:(TabStripModel::ContextMenuCommand)command |
| 767 forController:(TabController*)controller { | 779 forController:(TabController*)controller { |
| 768 int index = [self modelIndexForTabView:[controller view]]; | 780 int index = [self modelIndexForTabView:[controller view]]; |
| 769 if (!tabStripModel_->ContainsIndex(index)) | 781 if (!tabStripModel_->ContainsIndex(index)) |
| 770 return NO; | 782 return NO; |
| 771 return tabStripModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO; | 783 return tabStripModel_->IsContextMenuCommandEnabled(index, command) ? YES : NO; |
| 772 } | 784 } |
| 773 | 785 |
| 786 // Returns a context menu model for a given controller. Caller owns the result. | |
| 787 - (ui::SimpleMenuModel*)contextMenuModelForController:(TabController*)controller | |
| 788 menuDelegate:(ui::SimpleMenuModel::Delegate*)delegate { | |
| 789 int index = [self modelIndexForTabView:[controller view]]; | |
| 790 return new TabMenuModel(delegate, tabStripModel_, index); | |
| 791 } | |
| 792 | |
| 774 - (void)insertPlaceholderForTab:(TabView*)tab | 793 - (void)insertPlaceholderForTab:(TabView*)tab |
| 775 frame:(NSRect)frame | 794 frame:(NSRect)frame |
| 776 yStretchiness:(CGFloat)yStretchiness { | 795 yStretchiness:(CGFloat)yStretchiness { |
| 777 placeholderTab_ = tab; | 796 placeholderTab_ = tab; |
| 778 placeholderFrame_ = frame; | 797 placeholderFrame_ = frame; |
| 779 placeholderStretchiness_ = yStretchiness; | 798 placeholderStretchiness_ = yStretchiness; |
| 780 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:NO]; | 799 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:NO]; |
| 781 } | 800 } |
| 782 | 801 |
| 783 - (BOOL)isDragSessionActive { | 802 - (BOOL)isDragSessionActive { |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1143 object:self]; | 1162 object:self]; |
| 1144 } | 1163 } |
| 1145 | 1164 |
| 1146 // Called when a notification is received from the model to select a particular | 1165 // Called when a notification is received from the model to select a particular |
| 1147 // tab. Swaps in the toolbar and content area associated with |newContents|. | 1166 // tab. Swaps in the toolbar and content area associated with |newContents|. |
| 1148 - (void)selectTabWithContents:(TabContentsWrapper*)newContents | 1167 - (void)selectTabWithContents:(TabContentsWrapper*)newContents |
| 1149 previousContents:(TabContentsWrapper*)oldContents | 1168 previousContents:(TabContentsWrapper*)oldContents |
| 1150 atIndex:(NSInteger)modelIndex | 1169 atIndex:(NSInteger)modelIndex |
| 1151 userGesture:(bool)wasUserGesture { | 1170 userGesture:(bool)wasUserGesture { |
| 1152 // Take closing tabs into account. | 1171 // Take closing tabs into account. |
| 1153 NSInteger index = [self indexFromModelIndex:modelIndex]; | 1172 NSInteger activeIndex = [self indexFromModelIndex:modelIndex]; |
| 1154 | 1173 |
| 1155 if (oldContents && oldContents != newContents) { | 1174 if (oldContents && oldContents != newContents) { |
| 1156 int oldModelIndex = | 1175 int oldModelIndex = |
| 1157 browser_->GetIndexOfController(&(oldContents->controller())); | 1176 browser_->GetIndexOfController(&(oldContents->controller())); |
| 1158 if (oldModelIndex != -1) { // When closing a tab, the old tab may be gone. | 1177 if (oldModelIndex != -1) { // When closing a tab, the old tab may be gone. |
| 1159 NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex]; | 1178 NSInteger oldIndex = [self indexFromModelIndex:oldModelIndex]; |
| 1160 TabContentsController* oldController = | 1179 TabContentsController* oldController = |
| 1161 [tabContentsArray_ objectAtIndex:oldIndex]; | 1180 [tabContentsArray_ objectAtIndex:oldIndex]; |
| 1162 [oldController willBecomeUnselectedTab]; | 1181 [oldController willBecomeUnselectedTab]; |
| 1163 oldContents->view()->StoreFocus(); | 1182 oldContents->view()->StoreFocus(); |
| 1164 oldContents->tab_contents()->WasHidden(); | 1183 oldContents->tab_contents()->WasHidden(); |
| 1165 } | 1184 } |
| 1166 } | 1185 } |
| 1167 | 1186 |
| 1168 // De-select all other tabs and select the new tab. | 1187 // First get the vector of indices, which is allays sorted in ascending order. |
| 1188 TabStripSelectionModel::SelectedIndices selection( | |
| 1189 tabStripModel_->selection_model().selected_indices()); | |
| 1190 // Iterate through all of the tabs, selecting each as necessary. | |
| 1191 TabStripSelectionModel::SelectedIndices::iterator iter = selection.begin(); | |
| 1169 int i = 0; | 1192 int i = 0; |
| 1170 for (TabController* current in tabArray_.get()) { | 1193 for (TabController* current in tabArray_.get()) { |
| 1171 [current setSelected:(i == index) ? YES : NO]; | 1194 BOOL selected = iter != selection.end() && |
| 1195 [self indexFromModelIndex:*iter] == i; | |
| 1196 [current setSelected:selected]; | |
| 1197 [current setActive:i == activeIndex]; | |
| 1198 if (selected) | |
| 1199 ++iter; | |
| 1172 ++i; | 1200 ++i; |
| 1173 } | 1201 } |
| 1174 | 1202 |
| 1175 // Tell the new tab contents it is about to become the selected tab. Here it | 1203 // Tell the new tab contents it is about to become the selected tab. Here it |
| 1176 // can do things like make sure the toolbar is up to date. | 1204 // can do things like make sure the toolbar is up to date. |
| 1177 TabContentsController* newController = | 1205 TabContentsController* newController = |
| 1178 [tabContentsArray_ objectAtIndex:index]; | 1206 [tabContentsArray_ objectAtIndex:activeIndex]; |
| 1179 [newController willBecomeSelectedTab]; | 1207 [newController willBecomeSelectedTab]; |
| 1180 | 1208 |
| 1181 // Relayout for new tabs and to let the selected tab grow to be larger in | 1209 // Relayout for new tabs and to let the selected tab grow to be larger in |
| 1182 // size than surrounding tabs if the user has many. This also raises the | 1210 // size than surrounding tabs if the user has many. This also raises the |
| 1183 // selected tab to the top. | 1211 // selected tab to the top. |
| 1184 [self layoutTabs]; | 1212 [self layoutTabs]; |
| 1185 | 1213 |
| 1186 // Swap in the contents for the new tab. | 1214 // Swap in the contents for the new tab. |
| 1187 [self swapInTabAtIndex:modelIndex]; | 1215 [self swapInTabAtIndex:modelIndex]; |
| 1188 | 1216 |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1741 // |-regenerateSubviewList| to actually add it). | 1769 // |-regenerateSubviewList| to actually add it). |
| 1742 - (void)regenerateSubviewList { | 1770 - (void)regenerateSubviewList { |
| 1743 // Remove self as an observer from all the old tabs before a new set of | 1771 // Remove self as an observer from all the old tabs before a new set of |
| 1744 // potentially different tabs is put in place. | 1772 // potentially different tabs is put in place. |
| 1745 [self setTabTrackingAreasEnabled:NO]; | 1773 [self setTabTrackingAreasEnabled:NO]; |
| 1746 | 1774 |
| 1747 // Subviews to put in (in bottom-to-top order), beginning with the permanent | 1775 // Subviews to put in (in bottom-to-top order), beginning with the permanent |
| 1748 // ones. | 1776 // ones. |
| 1749 NSMutableArray* subviews = [NSMutableArray arrayWithArray:permanentSubviews_]; | 1777 NSMutableArray* subviews = [NSMutableArray arrayWithArray:permanentSubviews_]; |
| 1750 | 1778 |
| 1751 NSView* selectedTabView = nil; | 1779 NSView* selectedTabView = nil; |
|
Avi (use Gerrit)
2011/04/08 15:22:20
If we're renaming the concept of "selected" to "ac
Robert Sesek
2011/04/09 14:23:07
Done.
| |
| 1752 // Go through tabs in reverse order, since |subviews| is bottom-to-top. | 1780 // Go through tabs in reverse order, since |subviews| is bottom-to-top. |
| 1753 for (TabController* tab in [tabArray_ reverseObjectEnumerator]) { | 1781 for (TabController* tab in [tabArray_ reverseObjectEnumerator]) { |
| 1754 NSView* tabView = [tab view]; | 1782 NSView* tabView = [tab view]; |
| 1755 if ([tab selected]) { | 1783 if ([tab active]) { |
| 1756 DCHECK(!selectedTabView); | 1784 DCHECK(!selectedTabView); |
| 1757 selectedTabView = tabView; | 1785 selectedTabView = tabView; |
| 1758 } else { | 1786 } else { |
| 1759 [subviews addObject:tabView]; | 1787 [subviews addObject:tabView]; |
| 1760 } | 1788 } |
| 1761 } | 1789 } |
| 1762 if (selectedTabView) { | 1790 if (selectedTabView) { |
| 1763 [subviews addObject:selectedTabView]; | 1791 [subviews addObject:selectedTabView]; |
| 1764 } | 1792 } |
| 1765 [tabStripView_ setSubviews:subviews]; | 1793 [tabStripView_ setSubviews:subviews]; |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2088 } | 2116 } |
| 2089 | 2117 |
| 2090 NSString* menuTitle = | 2118 NSString* menuTitle = |
| 2091 l10n_util::GetNSStringWithFixup(IDS_PROFILES_CREATE_NEW_PROFILE_OPTION); | 2119 l10n_util::GetNSStringWithFixup(IDS_PROFILES_CREATE_NEW_PROFILE_OPTION); |
| 2092 [menu addItemWithTitle:menuTitle | 2120 [menu addItemWithTitle:menuTitle |
| 2093 action:NULL | 2121 action:NULL |
| 2094 keyEquivalent:@""]; | 2122 keyEquivalent:@""]; |
| 2095 } | 2123 } |
| 2096 | 2124 |
| 2097 @end | 2125 @end |
| OLD | NEW |