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> |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "chrome/browser/sidebar/sidebar_container.h" | 25 #include "chrome/browser/sidebar/sidebar_container.h" |
26 #include "chrome/browser/sidebar/sidebar_manager.h" | 26 #include "chrome/browser/sidebar/sidebar_manager.h" |
27 #include "chrome/browser/tabs/tab_strip_model.h" | 27 #include "chrome/browser/tabs/tab_strip_model.h" |
28 #include "chrome/browser/tabs/tab_strip_selection_model.h" | 28 #include "chrome/browser/tabs/tab_strip_selection_model.h" |
29 #include "chrome/browser/ui/browser.h" | 29 #include "chrome/browser/ui/browser.h" |
30 #include "chrome/browser/ui/browser_navigator.h" | 30 #include "chrome/browser/ui/browser_navigator.h" |
31 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 31 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
32 #import "chrome/browser/ui/cocoa/constrained_window_mac.h" | 32 #import "chrome/browser/ui/cocoa/constrained_window_mac.h" |
33 #import "chrome/browser/ui/cocoa/image_button_cell.h" | 33 #import "chrome/browser/ui/cocoa/image_button_cell.h" |
34 #import "chrome/browser/ui/cocoa/new_tab_button.h" | 34 #import "chrome/browser/ui/cocoa/new_tab_button.h" |
35 #import "chrome/browser/ui/cocoa/profile_menu_button.h" | |
36 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util.h" | 35 #import "chrome/browser/ui/cocoa/tab_contents/favicon_util.h" |
37 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h" | 36 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h" |
38 #import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h" | 37 #import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h" |
39 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" | 38 #import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h" |
40 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" | 39 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h" |
41 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" | 40 #import "chrome/browser/ui/cocoa/tabs/tab_view.h" |
42 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" | 41 #import "chrome/browser/ui/cocoa/tabs/throbber_view.h" |
43 #import "chrome/browser/ui/cocoa/tracking_area.h" | 42 #import "chrome/browser/ui/cocoa/tracking_area.h" |
44 #include "chrome/browser/ui/find_bar/find_bar.h" | 43 #include "chrome/browser/ui/find_bar/find_bar.h" |
45 #include "chrome/browser/ui/find_bar/find_bar_controller.h" | 44 #include "chrome/browser/ui/find_bar/find_bar_controller.h" |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 strip_ = nil; | 264 strip_ = nil; |
266 controller_ = nil; | 265 controller_ = nil; |
267 } | 266 } |
268 | 267 |
269 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { | 268 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { |
270 [strip_ animationDidStopForController:controller_ finished:finished]; | 269 [strip_ animationDidStopForController:controller_ finished:finished]; |
271 } | 270 } |
272 | 271 |
273 @end | 272 @end |
274 | 273 |
275 namespace TabStripControllerInternal { | |
276 | |
277 // Bridges C++ notifications back to the TabStripController. | |
278 class NotificationBridge : public NotificationObserver { | |
279 public: | |
280 explicit NotificationBridge(TabStripController* controller, | |
281 PrefService* prefService) | |
282 : controller_(controller) { | |
283 DCHECK(prefService); | |
284 usernamePref_.Init(prefs::kGoogleServicesUsername, prefService, this); | |
285 } | |
286 | |
287 // Overridden from NotificationObserver: | |
288 virtual void Observe(NotificationType type, | |
289 const NotificationSource& source, | |
290 const NotificationDetails& details) { | |
291 DCHECK_EQ(NotificationType::PREF_CHANGED, type.value); | |
292 std::string* name = Details<std::string>(details).ptr(); | |
293 if (prefs::kGoogleServicesUsername == *name) { | |
294 [controller_ updateProfileMenuButton]; | |
295 [controller_ layoutTabsWithAnimation:NO regenerateSubviews:NO]; | |
296 } | |
297 } | |
298 | |
299 private: | |
300 TabStripController* controller_; // weak, owns us | |
301 | |
302 // The Google services user name associated with this BrowserView's profile. | |
303 StringPrefMember usernamePref_; | |
304 }; | |
305 | |
306 } // namespace TabStripControllerInternal | |
307 | |
308 #pragma mark - | 274 #pragma mark - |
309 | 275 |
310 // In general, there is a one-to-one correspondence between TabControllers, | 276 // In general, there is a one-to-one correspondence between TabControllers, |
311 // TabViews, TabContentsControllers, and the TabContents in the TabStripModel. | 277 // TabViews, TabContentsControllers, and the TabContents in the TabStripModel. |
312 // In the steady-state, the indices line up so an index coming from the model | 278 // In the steady-state, the indices line up so an index coming from the model |
313 // is directly mapped to the same index in the parallel arrays holding our | 279 // is directly mapped to the same index in the parallel arrays holding our |
314 // views and controllers. This is also true when new tabs are created (even | 280 // views and controllers. This is also true when new tabs are created (even |
315 // though there is a small period of animation) because the tab is present | 281 // though there is a small period of animation) because the tab is present |
316 // in the model while the TabView is animating into place. As a result, nothing | 282 // in the model while the TabView is animating into place. As a result, nothing |
317 // special need be done to handle "new tab" animation. | 283 // special need be done to handle "new tab" animation. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 | 343 |
378 // TODO(viettrungluu): WTF? "For some reason, if the view is present in the | 344 // TODO(viettrungluu): WTF? "For some reason, if the view is present in the |
379 // nib a priori, it draws correctly. If we create it in code and add it to | 345 // nib a priori, it draws correctly. If we create it in code and add it to |
380 // the tab view, it draws with all sorts of crazy artifacts." | 346 // the tab view, it draws with all sorts of crazy artifacts." |
381 newTabButton_ = [view getNewTabButton]; | 347 newTabButton_ = [view getNewTabButton]; |
382 [self addSubviewToPermanentList:newTabButton_]; | 348 [self addSubviewToPermanentList:newTabButton_]; |
383 [newTabButton_ setTarget:nil]; | 349 [newTabButton_ setTarget:nil]; |
384 [newTabButton_ setAction:@selector(commandDispatch:)]; | 350 [newTabButton_ setAction:@selector(commandDispatch:)]; |
385 [newTabButton_ setTag:IDC_NEW_TAB]; | 351 [newTabButton_ setTag:IDC_NEW_TAB]; |
386 | 352 |
387 profileMenuButton_ = [view profileMenuButton]; | |
388 [self addSubviewToPermanentList:profileMenuButton_]; | |
389 [self updateProfileMenuButton]; | |
390 // Register pref observers for profile name. | |
391 notificationBridge_.reset( | |
392 new TabStripControllerInternal::NotificationBridge( | |
393 self, browser_->profile()->GetPrefs())); | |
394 | |
395 // Set the images from code because Cocoa fails to find them in our sub | 353 // Set the images from code because Cocoa fails to find them in our sub |
396 // bundle during tests. | 354 // bundle during tests. |
397 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON | 355 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON |
398 forButtonState:image_button_cell::kDefaultState]; | 356 forButtonState:image_button_cell::kDefaultState]; |
399 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON_H | 357 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON_H |
400 forButtonState:image_button_cell::kHoverState]; | 358 forButtonState:image_button_cell::kHoverState]; |
401 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON_P | 359 [[newTabButton_ cell] setImageID:IDR_NEWTAB_BUTTON_P |
402 forButtonState:image_button_cell::kPressedState]; | 360 forButtonState:image_button_cell::kPressedState]; |
403 newTabButtonShowingHoverImage_ = NO; | 361 newTabButtonShowingHoverImage_ = NO; |
404 newTabTrackingArea_.reset( | 362 newTabTrackingArea_.reset( |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 } | 1032 } |
1075 [[newTabButton_ animator] setFrame:newTabNewFrame]; | 1033 [[newTabButton_ animator] setFrame:newTabNewFrame]; |
1076 newTabTargetFrame_ = newTabNewFrame; | 1034 newTabTargetFrame_ = newTabNewFrame; |
1077 } else { | 1035 } else { |
1078 [newTabButton_ setFrame:newTabNewFrame]; | 1036 [newTabButton_ setFrame:newTabNewFrame]; |
1079 newTabTargetFrame_ = newTabNewFrame; | 1037 newTabTargetFrame_ = newTabNewFrame; |
1080 } | 1038 } |
1081 } | 1039 } |
1082 } | 1040 } |
1083 | 1041 |
1084 if (profileMenuButton_ && ![profileMenuButton_ isHidden]) { | |
1085 CGFloat maxX; | |
1086 if ([newTabButton_ isHidden]) { | |
1087 maxX = std::max(offset, NSMaxX(placeholderFrame_) - kTabOverlap); | |
1088 } else { | |
1089 maxX = NSMaxX(newTabTargetFrame_); | |
1090 } | |
1091 NSRect profileMenuButtonFrame = [profileMenuButton_ frame]; | |
1092 NSSize minSize = [profileMenuButton_ minControlSize]; | |
1093 | |
1094 // Make room for the full screen button if necessary. | |
1095 if (!hasUpdatedProfileMenuButtonXOffset_) { | |
1096 hasUpdatedProfileMenuButtonXOffset_ = YES; | |
1097 if ([[profileMenuButton_ window] | |
1098 respondsToSelector:@selector(toggleFullScreen:)]) { | |
1099 NSButton* fullscreenButton = [[profileMenuButton_ window] | |
1100 standardWindowButton:NSWindowFullScreenButton]; | |
1101 if (fullscreenButton) { | |
1102 profileMenuButtonFrame.origin.x = NSMinX([fullscreenButton frame]) - | |
1103 NSWidth(profileMenuButtonFrame) - kProfileMenuButtonOffset; | |
1104 } | |
1105 } | |
1106 } | |
1107 | |
1108 // TODO(sail): Animate this. | |
1109 CGFloat availableWidth = NSMaxX(profileMenuButtonFrame) - maxX - | |
1110 kProfileMenuButtonOffset; | |
1111 if (availableWidth > minSize.width) { | |
1112 [profileMenuButton_ setShouldShowProfileDisplayName:YES]; | |
1113 } else { | |
1114 [profileMenuButton_ setShouldShowProfileDisplayName:NO]; | |
1115 } | |
1116 | |
1117 NSSize desiredSize = [profileMenuButton_ desiredControlSize]; | |
1118 NSRect rect; | |
1119 rect.size.width = std::min(desiredSize.width, | |
1120 std::max(availableWidth, minSize.width)); | |
1121 rect.size.height = desiredSize.height; | |
1122 rect.origin.y = NSMaxY(profileMenuButtonFrame) - rect.size.height; | |
1123 rect.origin.x = NSMaxX(profileMenuButtonFrame) - rect.size.width; | |
1124 [profileMenuButton_ setFrame:rect]; | |
1125 } | |
1126 | |
1127 [dragBlockingView_ setFrame:enclosingRect]; | 1042 [dragBlockingView_ setFrame:enclosingRect]; |
1128 | 1043 |
1129 // Mark that we've successfully completed layout of at least one tab. | 1044 // Mark that we've successfully completed layout of at least one tab. |
1130 initialLayoutComplete_ = YES; | 1045 initialLayoutComplete_ = YES; |
1131 } | 1046 } |
1132 | 1047 |
1133 // When we're told to layout from the public API we usually want to animate, | 1048 // When we're told to layout from the public API we usually want to animate, |
1134 // except when it's the first time. | 1049 // except when it's the first time. |
1135 - (void)layoutTabs { | 1050 - (void)layoutTabs { |
1136 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES]; | 1051 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES]; |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2118 NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView]; | 2033 NSInteger modelIndex = [self modelIndexForContentsView:tabContentsView]; |
2119 NSInteger index = [self indexFromModelIndex:modelIndex]; | 2034 NSInteger index = [self indexFromModelIndex:modelIndex]; |
2120 BrowserWindowController* controller = | 2035 BrowserWindowController* controller = |
2121 (BrowserWindowController*)[[switchView_ window] windowController]; | 2036 (BrowserWindowController*)[[switchView_ window] windowController]; |
2122 DCHECK(index >= 0); | 2037 DCHECK(index >= 0); |
2123 if (index >= 0) { | 2038 if (index >= 0) { |
2124 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; | 2039 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; |
2125 } | 2040 } |
2126 } | 2041 } |
2127 | 2042 |
2128 - (BOOL)shouldShowProfileMenuButton { | |
2129 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles)) | |
2130 return NO; | |
2131 if (browser_->profile()->IsOffTheRecord()) | |
2132 return NO; | |
2133 return (!browser_->profile()->GetPrefs()->GetString( | |
2134 prefs::kGoogleServicesUsername).empty()); | |
2135 } | |
2136 | |
2137 - (void)updateProfileMenuButton { | |
2138 if (![self shouldShowProfileMenuButton]) { | |
2139 [profileMenuButton_ setHidden:YES]; | |
2140 return; | |
2141 } | |
2142 | |
2143 std::string profileName = browser_->profile()->GetPrefs()->GetString( | |
2144 prefs::kGoogleServicesUsername); | |
2145 [profileMenuButton_ setProfileDisplayName: | |
2146 [NSString stringWithUTF8String:profileName.c_str()]]; | |
2147 [profileMenuButton_ setHidden:NO]; | |
2148 } | |
2149 | |
2150 @end | 2043 @end |
OLD | NEW |