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 |