| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "ios/chrome/browser/ui/tabs/tab_strip_controller.h" | 5 #import "ios/chrome/browser/ui/tabs/tab_strip_controller.h" |
| 6 #import "ios/chrome/browser/ui/tabs/tab_strip_controller_private.h" | 6 #import "ios/chrome/browser/ui/tabs/tab_strip_controller_private.h" |
| 7 | 7 |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 const NSTimeInterval kDragAndDropLongPressDuration = 0.4; | 65 const NSTimeInterval kDragAndDropLongPressDuration = 0.4; |
| 66 | 66 |
| 67 // Tab dimensions. | 67 // Tab dimensions. |
| 68 const CGFloat kTabOverlap = 26.0; | 68 const CGFloat kTabOverlap = 26.0; |
| 69 const CGFloat kTabOverlapForCompactLayout = 30.0; | 69 const CGFloat kTabOverlapForCompactLayout = 30.0; |
| 70 | 70 |
| 71 const CGFloat kNewTabOverlap = 8.0; | 71 const CGFloat kNewTabOverlap = 8.0; |
| 72 const CGFloat kMaxTabWidth = 265.0; | 72 const CGFloat kMaxTabWidth = 265.0; |
| 73 const CGFloat kMaxTabWidthForCompactLayout = 225.0; | 73 const CGFloat kMaxTabWidthForCompactLayout = 225.0; |
| 74 | 74 |
| 75 // Toggle button dimensions. | 75 // Tab Switcher button dimensions. |
| 76 const CGFloat kModeToggleButtonWidth = 36.0; | 76 const CGFloat kTabSwitcherButtonWidth = 46.0; |
| 77 const CGFloat kTabSwitcherToggleButtonWidth = 46.0; | 77 const CGFloat kTabSwitcherButtonBackgroundWidth = 62.0; |
| 78 const CGFloat kModeToggleButtonBackgroundWidth = 62.0; | |
| 79 | 78 |
| 80 const CGFloat kNewTabRightPadding = 4.0; | 79 const CGFloat kNewTabRightPadding = 4.0; |
| 81 const CGFloat kMinTabWidth = 200.0; | 80 const CGFloat kMinTabWidth = 200.0; |
| 82 const CGFloat kMinTabWidthForCompactLayout = 160.0; | 81 const CGFloat kMinTabWidthForCompactLayout = 160.0; |
| 83 | 82 |
| 84 const CGFloat kCollapsedTabOverlap = 5.0; | 83 const CGFloat kCollapsedTabOverlap = 5.0; |
| 85 const NSUInteger kMaxNumCollapsedTabs = 3; | 84 const NSUInteger kMaxNumCollapsedTabs = 3; |
| 86 const NSUInteger kMaxNumCollapsedTabsForCompactLayout = 0; | 85 const NSUInteger kMaxNumCollapsedTabsForCompactLayout = 0; |
| 87 | 86 |
| 88 // Tabs with a visible width smaller than this draw as collapsed tabs.. | 87 // Tabs with a visible width smaller than this draw as collapsed tabs.. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 116 } | 115 } |
| 117 | 116 |
| 118 @interface TabStripController ()<TabModelObserver, | 117 @interface TabStripController ()<TabModelObserver, |
| 119 TabStripViewLayoutDelegate, | 118 TabStripViewLayoutDelegate, |
| 120 UIGestureRecognizerDelegate, | 119 UIGestureRecognizerDelegate, |
| 121 UIScrollViewDelegate> { | 120 UIScrollViewDelegate> { |
| 122 base::scoped_nsobject<TabModel> _tabModel; | 121 base::scoped_nsobject<TabModel> _tabModel; |
| 123 UIView* _view; | 122 UIView* _view; |
| 124 TabStripView* _tabStripView; | 123 TabStripView* _tabStripView; |
| 125 UIButton* _buttonNewTab; | 124 UIButton* _buttonNewTab; |
| 126 // TODO(crbug.com/687132): Remove toggle button. | 125 base::scoped_nsobject<UIButton> _tabSwitcherButton; |
| 127 UIButton* _modeToggleButton; // weak, nil if not visible. | |
| 128 UIButton* _tabSwitcherToggleButton; // weak, nil if not visible. | |
| 129 | 126 |
| 130 // Background view of the toggle button. Only visible while in compact layout. | 127 // Background view of the tab switcher button. Only visible while in compact |
| 131 base::scoped_nsobject<UIImageView> _toggleButtonBackgroundView; | 128 // layout. |
| 129 base::scoped_nsobject<UIImageView> _tabSwitcherButtonBackgroundView; |
| 132 | 130 |
| 133 TabStrip::Style _style; | 131 TabStrip::Style _style; |
| 134 base::WeakNSProtocol<id<FullScreenControllerDelegate>> _fullscreenDelegate; | 132 base::WeakNSProtocol<id<FullScreenControllerDelegate>> _fullscreenDelegate; |
| 135 | 133 |
| 136 // Array of TabViews. There is a one-to-one correspondence between this array | 134 // Array of TabViews. There is a one-to-one correspondence between this array |
| 137 // and the set of Tabs in the TabModel. | 135 // and the set of Tabs in the TabModel. |
| 138 base::scoped_nsobject<NSMutableArray> _tabArray; | 136 base::scoped_nsobject<NSMutableArray> _tabArray; |
| 139 | 137 |
| 140 // Set of TabViews that are currently closing. These TabViews are also in | 138 // Set of TabViews that are currently closing. These TabViews are also in |
| 141 // |_tabArray|. Used to translate between |_tabArray| indexes and TabModel | 139 // |_tabArray|. Used to translate between |_tabArray| indexes and TabModel |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 NSTimer* _autoscrollTimer; // weak | 177 NSTimer* _autoscrollTimer; // weak |
| 180 | 178 |
| 181 // The distance to scroll for each autoscroll timer tick. If negative, the | 179 // The distance to scroll for each autoscroll timer tick. If negative, the |
| 182 // tabstrip will scroll to the left; if positive, to the right. | 180 // tabstrip will scroll to the left; if positive, to the right. |
| 183 CGFloat _autoscrollDistance; | 181 CGFloat _autoscrollDistance; |
| 184 | 182 |
| 185 // The model index of the placeholder gap, if one exists. This value is used | 183 // The model index of the placeholder gap, if one exists. This value is used |
| 186 // as the new model index of the dragged tab when it is dropped. | 184 // as the new model index of the dragged tab when it is dropped. |
| 187 NSUInteger _placeholderGapModelIndex; | 185 NSUInteger _placeholderGapModelIndex; |
| 188 | 186 |
| 189 // If YES, display the mode toggle switch at the left side of the strip. Can | |
| 190 // be set after creation. | |
| 191 BOOL _hasModeToggleSwitch; | |
| 192 | |
| 193 // If YES, display the tab switcher toggle switch at the left side of the | |
| 194 // strip. Can be set after creation. | |
| 195 BOOL _hasTabSwitcherToggleSwitch; | |
| 196 | |
| 197 base::mac::ObjCPropertyReleaser _propertyReleaser_TabStripController; | 187 base::mac::ObjCPropertyReleaser _propertyReleaser_TabStripController; |
| 198 } | 188 } |
| 199 | 189 |
| 200 @property(nonatomic, readonly, retain) TabStripView* tabStripView; | 190 @property(nonatomic, readonly, retain) TabStripView* tabStripView; |
| 201 @property(nonatomic, readonly, retain) UIButton* buttonNewTab; | 191 @property(nonatomic, readonly, retain) UIButton* buttonNewTab; |
| 202 @property(nonatomic, readonly, assign) UIButton* tabSwitcherToggleButton; | |
| 203 | 192 |
| 204 // Initializes the tab array based on the the entries in the TabModel. Creates | 193 // Initializes the tab array based on the the entries in the TabModel. Creates |
| 205 // one TabView per Tab and adds it to the tabstrip. A later call to | 194 // one TabView per Tab and adds it to the tabstrip. A later call to |
| 206 // |-layoutTabs| is needed to properly place the tabs in the correct positions. | 195 // |-layoutTabs| is needed to properly place the tabs in the correct positions. |
| 207 - (void)initializeTabArrayFromTabModel; | 196 - (void)initializeTabArrayFromTabModel; |
| 208 | 197 |
| 209 // Initializes the tab array to have only one empty tab, for the case (used | 198 // Initializes the tab array to have only one empty tab, for the case (used |
| 210 // during startup) when there is not a tab model available. | 199 // during startup) when there is not a tab model available. |
| 211 - (void)initializeTabArrayWithNoModel; | 200 - (void)initializeTabArrayWithNoModel; |
| 212 | 201 |
| 213 // Add and remove the mode toggle icon and adjusts the size of the scroll view | |
| 214 // accordingly. Assumes incognito style has already been checked. | |
| 215 - (void)installModeToggleButton; | |
| 216 - (void)removeModeToggleButton; | |
| 217 | |
| 218 // Add and remove the tab switcher toggle icon and adjusts the size of the | |
| 219 // scroll view accordingly. The tab switcher toggle button is replacing the | |
| 220 // incognito mode toggle button. | |
| 221 // TODO:(jbbegue) crbug/477676 Remove reference to the incognito toggle button | |
| 222 // once we know for sure that it will be replaced by the tab switcher toggle | |
| 223 // button. | |
| 224 - (void)installTabSwitcherToggleButton; | |
| 225 - (void)removeTabSwitcherToggleButton; | |
| 226 | |
| 227 // Returns an autoreleased TabView object with no content. | 202 // Returns an autoreleased TabView object with no content. |
| 228 - (TabView*)emptyTabView; | 203 - (TabView*)emptyTabView; |
| 229 | 204 |
| 230 // Returns an autoreleased TabView object based on the given Tab. | 205 // Returns an autoreleased TabView object based on the given Tab. |
| 231 // |isSelected| is passed in here as an optimization, so that the TabView is | 206 // |isSelected| is passed in here as an optimization, so that the TabView is |
| 232 // drawn correctly the first time, without requiring the model to send a | 207 // drawn correctly the first time, without requiring the model to send a |
| 233 // -setSelected message to the TabView. | 208 // -setSelected message to the TabView. |
| 234 - (TabView*)tabViewForTab:(Tab*)tab isSelected:(BOOL)isSelected; | 209 - (TabView*)tabViewForTab:(Tab*)tab isSelected:(BOOL)isSelected; |
| 235 | 210 |
| 236 // Creates and installs the view used to dim unselected tabs. Does nothing if | 211 // Creates and installs the view used to dim unselected tabs. Does nothing if |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 | 253 |
| 279 #if 0 | 254 #if 0 |
| 280 // Returns the appropriate model index for the currently dragged tab, given its | 255 // Returns the appropriate model index for the currently dragged tab, given its |
| 281 // current position. (If dropped, the tab would be at this index in the model.) | 256 // current position. (If dropped, the tab would be at this index in the model.) |
| 282 // TODO(rohitrao): Implement this method. | 257 // TODO(rohitrao): Implement this method. |
| 283 - (NSUInteger)modelIndexForDraggedTab; | 258 - (NSUInteger)modelIndexForDraggedTab; |
| 284 #endif | 259 #endif |
| 285 | 260 |
| 286 // Returns the horizontal visible tab strip width used to compute the tab width | 261 // Returns the horizontal visible tab strip width used to compute the tab width |
| 287 // and the tabs and new tab button in regular layout mode. | 262 // and the tabs and new tab button in regular layout mode. |
| 288 // Takes into account whether or not the mode toggle button is showing. | |
| 289 - (CGFloat)tabStripVisibleSpace; | 263 - (CGFloat)tabStripVisibleSpace; |
| 290 | 264 |
| 291 // Shift all of the tab strip subviews by an amount equal to the content offset | 265 // Shift all of the tab strip subviews by an amount equal to the content offset |
| 292 // change, which effectively places the subviews back where they were before the | 266 // change, which effectively places the subviews back where they were before the |
| 293 // change, in terms of screen coordinates. | 267 // change, in terms of screen coordinates. |
| 294 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset; | 268 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset; |
| 295 | 269 |
| 296 // Updates the scroll view's content size based on the current set of tabs and | 270 // Updates the scroll view's content size based on the current set of tabs and |
| 297 // closing tabs. After updating the content size, repositions views so they | 271 // closing tabs. After updating the content size, repositions views so they |
| 298 // they will appear stationary on screen. | 272 // they will appear stationary on screen. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 // Updates the content offset of the tab strip view in order to keep the | 305 // Updates the content offset of the tab strip view in order to keep the |
| 332 // selected tab view visible. | 306 // selected tab view visible. |
| 333 // Content offset adjustement is only needed/performed in compact mode or | 307 // Content offset adjustement is only needed/performed in compact mode or |
| 334 // regular mode for newly opened tabs. | 308 // regular mode for newly opened tabs. |
| 335 // This method must be called with a valid |tabIndex|. | 309 // This method must be called with a valid |tabIndex|. |
| 336 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex | 310 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex |
| 337 isNewTab:(BOOL)isNewTab; | 311 isNewTab:(BOOL)isNewTab; |
| 338 | 312 |
| 339 // Update the frame of the tab strip view (scrollview) frame, content inset and | 313 // Update the frame of the tab strip view (scrollview) frame, content inset and |
| 340 // toggle buttons states depending on the current layout mode. | 314 // toggle buttons states depending on the current layout mode. |
| 341 - (void)updateScrollViewFrameForToggleButton; | 315 - (void)updateScrollViewFrameForTabSwitcherButton; |
| 342 | 316 |
| 343 @end | 317 @end |
| 344 | 318 |
| 345 @implementation TabStripController | 319 @implementation TabStripController |
| 346 | 320 |
| 347 @synthesize buttonNewTab = _buttonNewTab; | 321 @synthesize buttonNewTab = _buttonNewTab; |
| 348 @synthesize hasModeToggleSwitch = _hasModeToggleSwitch; | |
| 349 @synthesize hasTabSwitcherToggleSwitch = _hasTabSwitcherToggleSwitch; | |
| 350 @synthesize highlightsSelectedTab = _highlightsSelectedTab; | 322 @synthesize highlightsSelectedTab = _highlightsSelectedTab; |
| 351 @synthesize modeToggleButton = _modeToggleButton; | |
| 352 @synthesize tabStripView = _tabStripView; | 323 @synthesize tabStripView = _tabStripView; |
| 353 @synthesize tabSwitcherToggleButton = _tabSwitcherToggleButton; | |
| 354 @synthesize view = _view; | 324 @synthesize view = _view; |
| 355 | 325 |
| 356 - (instancetype)initWithTabModel:(TabModel*)tabModel | 326 - (instancetype)initWithTabModel:(TabModel*)tabModel |
| 357 style:(TabStrip::Style)style { | 327 style:(TabStrip::Style)style { |
| 358 if ((self = [super init])) { | 328 if ((self = [super init])) { |
| 359 _propertyReleaser_TabStripController.Init(self, [TabStripController class]); | 329 _propertyReleaser_TabStripController.Init(self, [TabStripController class]); |
| 360 _tabArray.reset([[NSMutableArray alloc] initWithCapacity:10]); | 330 _tabArray.reset([[NSMutableArray alloc] initWithCapacity:10]); |
| 361 _closingTabs.reset([[NSMutableSet alloc] initWithCapacity:5]); | 331 _closingTabs.reset([[NSMutableSet alloc] initWithCapacity:5]); |
| 362 | 332 |
| 363 _tabModel.reset([tabModel retain]); | 333 _tabModel.reset([tabModel retain]); |
| 364 [_tabModel addObserver:self]; | 334 [_tabModel addObserver:self]; |
| 365 _style = style; | 335 _style = style; |
| 366 _hasModeToggleSwitch = NO; | |
| 367 _hasTabSwitcherToggleSwitch = NO; | |
| 368 | 336 |
| 369 // |self.view| setup. | 337 // |self.view| setup. |
| 370 CGRect tabStripFrame = [UIApplication sharedApplication].keyWindow.bounds; | 338 CGRect tabStripFrame = [UIApplication sharedApplication].keyWindow.bounds; |
| 371 tabStripFrame.size.height = kTabStripHeight; | 339 tabStripFrame.size.height = kTabStripHeight; |
| 372 _view = [[UIView alloc] initWithFrame:tabStripFrame]; | 340 _view = [[UIView alloc] initWithFrame:tabStripFrame]; |
| 373 _view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | | 341 _view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | |
| 374 UIViewAutoresizingFlexibleBottomMargin); | 342 UIViewAutoresizingFlexibleBottomMargin); |
| 375 _view.backgroundColor = TabStrip::BackgroundColor(); | 343 _view.backgroundColor = TabStrip::BackgroundColor(); |
| 376 if (UseRTLLayout()) | 344 if (UseRTLLayout()) |
| 377 _view.transform = CGAffineTransformMakeScale(-1, 1); | 345 _view.transform = CGAffineTransformMakeScale(-1, 1); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 // Use a nil target to send |-chromeExecuteCommand:| down the responder | 398 // Use a nil target to send |-chromeExecuteCommand:| down the responder |
| 431 // chain. | 399 // chain. |
| 432 [_buttonNewTab addTarget:nil | 400 [_buttonNewTab addTarget:nil |
| 433 action:@selector(chromeExecuteCommand:) | 401 action:@selector(chromeExecuteCommand:) |
| 434 forControlEvents:UIControlEventTouchUpInside]; | 402 forControlEvents:UIControlEventTouchUpInside]; |
| 435 [_buttonNewTab addTarget:self | 403 [_buttonNewTab addTarget:self |
| 436 action:@selector(recordUserMetrics:) | 404 action:@selector(recordUserMetrics:) |
| 437 forControlEvents:UIControlEventTouchUpInside]; | 405 forControlEvents:UIControlEventTouchUpInside]; |
| 438 [_tabStripView addSubview:_buttonNewTab]; | 406 [_tabStripView addSubview:_buttonNewTab]; |
| 439 | 407 |
| 408 [self installTabSwitcherButton]; |
| 409 |
| 440 // Add tab buttons to tab strip. | 410 // Add tab buttons to tab strip. |
| 441 if (_tabModel) | 411 if (_tabModel) |
| 442 [self initializeTabArrayFromTabModel]; | 412 [self initializeTabArrayFromTabModel]; |
| 443 else | 413 else |
| 444 [self initializeTabArrayWithNoModel]; | 414 [self initializeTabArrayWithNoModel]; |
| 445 | 415 |
| 446 // Update the layout of the tab buttons. | 416 // Update the layout of the tab buttons. |
| 447 [self updateContentSizeAndRepositionViews]; | 417 [self updateContentSizeAndRepositionViews]; |
| 448 [self layoutTabStripSubviews]; | 418 [self layoutTabStripSubviews]; |
| 449 | 419 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 | 456 |
| 487 - (void)initializeTabArrayWithNoModel { | 457 - (void)initializeTabArrayWithNoModel { |
| 488 DCHECK(!_tabModel); | 458 DCHECK(!_tabModel); |
| 489 TabView* view = [self emptyTabView]; | 459 TabView* view = [self emptyTabView]; |
| 490 [_tabArray addObject:view]; | 460 [_tabArray addObject:view]; |
| 491 [_tabStripView addSubview:view]; | 461 [_tabStripView addSubview:view]; |
| 492 [view setSelected:YES]; | 462 [view setSelected:YES]; |
| 493 return; | 463 return; |
| 494 } | 464 } |
| 495 | 465 |
| 496 - (void)setHasModeToggleSwitch:(BOOL)hasModeToggleSwitch { | |
| 497 if (_hasModeToggleSwitch && !hasModeToggleSwitch) | |
| 498 [self removeModeToggleButton]; | |
| 499 if (!_hasModeToggleSwitch && hasModeToggleSwitch) | |
| 500 [self installModeToggleButton]; | |
| 501 if (_hasModeToggleSwitch != hasModeToggleSwitch) { | |
| 502 _hasModeToggleSwitch = hasModeToggleSwitch; | |
| 503 [self updateContentSizeAndRepositionViews]; | |
| 504 [self setNeedsLayoutWithAnimation]; | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 - (void)setHasTabSwitcherToggleSwitch:(BOOL)hasTabSwitcherToggleSwitch { | |
| 509 if (_hasTabSwitcherToggleSwitch && !hasTabSwitcherToggleSwitch) | |
| 510 [self removeTabSwitcherToggleButton]; | |
| 511 if (!_hasTabSwitcherToggleSwitch && hasTabSwitcherToggleSwitch) | |
| 512 [self installTabSwitcherToggleButton]; | |
| 513 if (_hasTabSwitcherToggleSwitch != hasTabSwitcherToggleSwitch) { | |
| 514 _hasTabSwitcherToggleSwitch = hasTabSwitcherToggleSwitch; | |
| 515 [self updateContentSizeAndRepositionViews]; | |
| 516 [self setNeedsLayoutWithAnimation]; | |
| 517 } | |
| 518 } | |
| 519 | |
| 520 - (TabView*)emptyTabView { | 466 - (TabView*)emptyTabView { |
| 521 TabView* view = | 467 TabView* view = |
| 522 [[[TabView alloc] initWithEmptyView:YES selected:YES] autorelease]; | 468 [[[TabView alloc] initWithEmptyView:YES selected:YES] autorelease]; |
| 523 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; | 469 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; |
| 524 [view setContentMode:UIViewContentModeRedraw]; | 470 [view setContentMode:UIViewContentModeRedraw]; |
| 525 | 471 |
| 526 // Setting the tab to be hidden marks it as a new tab. The layout code will | 472 // Setting the tab to be hidden marks it as a new tab. The layout code will |
| 527 // make the tab visible and set up the appropriate animations. | 473 // make the tab visible and set up the appropriate animations. |
| 528 [view setHidden:YES]; | 474 [view setHidden:YES]; |
| 529 | 475 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 [_dimmingView removeFromSuperview]; | 569 [_dimmingView removeFromSuperview]; |
| 624 _dimmingView.reset(); | 570 _dimmingView.reset(); |
| 625 } | 571 } |
| 626 }]; | 572 }]; |
| 627 } | 573 } |
| 628 } | 574 } |
| 629 | 575 |
| 630 - (void)recordUserMetrics:(id)sender { | 576 - (void)recordUserMetrics:(id)sender { |
| 631 if (sender == _buttonNewTab) | 577 if (sender == _buttonNewTab) |
| 632 base::RecordAction(UserMetricsAction("MobileTabStripNewTab")); | 578 base::RecordAction(UserMetricsAction("MobileTabStripNewTab")); |
| 633 else if (sender == _modeToggleButton) | 579 else if (sender == _tabSwitcherButton.get()) |
| 634 base::RecordAction(UserMetricsAction("MobileTabStripSwitchMode")); | |
| 635 else if (sender == _tabSwitcherToggleButton) | |
| 636 base::RecordAction(UserMetricsAction("MobileTabSwitcherOpen")); | 580 base::RecordAction(UserMetricsAction("MobileTabSwitcherOpen")); |
| 637 else | 581 else |
| 638 LOG(WARNING) << "Trying to record metrics for unknown sender " | 582 LOG(WARNING) << "Trying to record metrics for unknown sender " |
| 639 << base::SysNSStringToUTF8([sender description]); | 583 << base::SysNSStringToUTF8([sender description]); |
| 640 } | 584 } |
| 641 | 585 |
| 642 - (void)tabTapped:(id)sender { | 586 - (void)tabTapped:(id)sender { |
| 643 DCHECK([sender isKindOfClass:[TabView class]]); | 587 DCHECK([sender isKindOfClass:[TabView class]]); |
| 644 | 588 |
| 645 // Ignore taps while in reordering mode. | 589 // Ignore taps while in reordering mode. |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 withTab:(Tab*)newTab | 1004 withTab:(Tab*)newTab |
| 1061 atIndex:(NSUInteger)index { | 1005 atIndex:(NSUInteger)index { |
| 1062 // TabViews do not hold references to their parent Tabs, so it's safe to treat | 1006 // TabViews do not hold references to their parent Tabs, so it's safe to treat |
| 1063 // this as a tab change rather than a tab replace. | 1007 // this as a tab change rather than a tab replace. |
| 1064 [self tabModel:model didChangeTab:newTab]; | 1008 [self tabModel:model didChangeTab:newTab]; |
| 1065 } | 1009 } |
| 1066 | 1010 |
| 1067 #pragma mark - | 1011 #pragma mark - |
| 1068 #pragma mark Views and Layout | 1012 #pragma mark Views and Layout |
| 1069 | 1013 |
| 1070 - (void)installModeToggleButton { | |
| 1071 // Add the mode toggle button view. | |
| 1072 DCHECK(!_modeToggleButton); | |
| 1073 UIImage* toggleIcon = nil; | |
| 1074 int toggleIdsAccessibilityLabel; | |
| 1075 NSString* toggleEnglishUiAutomationName; | |
| 1076 if (_style == TabStrip::kStyleDark) { | |
| 1077 toggleIcon = [UIImage imageNamed:@"tabstrip_switch"]; | |
| 1078 toggleIdsAccessibilityLabel = IDS_IOS_SWITCH_BROWSER_MODE_ENTER_INCOGNITO; | |
| 1079 toggleEnglishUiAutomationName = @"Enter Incognito* Mode"; | |
| 1080 } else { | |
| 1081 toggleIcon = [UIImage imageNamed:@"tabstrip_incognito_switch"]; | |
| 1082 toggleIdsAccessibilityLabel = IDS_IOS_SWITCH_BROWSER_MODE_LEAVE_INCOGNITO; | |
| 1083 toggleEnglishUiAutomationName = @"Leave Incognito* Mode"; | |
| 1084 } | |
| 1085 const CGFloat tabStripHeight = _view.frame.size.height; | |
| 1086 CGRect buttonFrame = | |
| 1087 CGRectMake(CGRectGetMaxX(_view.frame) - kModeToggleButtonWidth, 0.0, | |
| 1088 kModeToggleButtonWidth, tabStripHeight); | |
| 1089 _modeToggleButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |
| 1090 _modeToggleButton.frame = buttonFrame; | |
| 1091 [_modeToggleButton setImageEdgeInsets:UIEdgeInsetsMake(7, 5, 7, 5)]; | |
| 1092 _modeToggleButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; | |
| 1093 _modeToggleButton.backgroundColor = [UIColor clearColor]; | |
| 1094 [_modeToggleButton setImage:toggleIcon forState:UIControlStateNormal]; | |
| 1095 // Set target/action to bubble up with command id as tag. | |
| 1096 [_modeToggleButton addTarget:nil | |
| 1097 action:@selector(chromeExecuteCommand:) | |
| 1098 forControlEvents:UIControlEventTouchUpInside]; | |
| 1099 [_modeToggleButton addTarget:self | |
| 1100 action:@selector(recordUserMetrics:) | |
| 1101 forControlEvents:UIControlEventTouchUpInside]; | |
| 1102 | |
| 1103 SetA11yLabelAndUiAutomationName(_modeToggleButton, | |
| 1104 toggleIdsAccessibilityLabel, | |
| 1105 toggleEnglishUiAutomationName); | |
| 1106 [_view addSubview:_modeToggleButton]; | |
| 1107 // Shrink the scroll view. | |
| 1108 [self updateScrollViewFrameForToggleButton]; | |
| 1109 } | |
| 1110 | |
| 1111 - (void)removeModeToggleButton { | |
| 1112 // Remove the button view. | |
| 1113 DCHECK(_modeToggleButton); | |
| 1114 [_modeToggleButton removeFromSuperview]; | |
| 1115 _modeToggleButton = nil; | |
| 1116 // Extend the scroll view. | |
| 1117 [self updateScrollViewFrameForToggleButton]; | |
| 1118 } | |
| 1119 | |
| 1120 - (CGFloat)tabStripVisibleSpace { | 1014 - (CGFloat)tabStripVisibleSpace { |
| 1121 CGFloat availableSpace = CGRectGetWidth([_tabStripView bounds]) - | 1015 CGFloat availableSpace = CGRectGetWidth([_tabStripView bounds]) - |
| 1122 CGRectGetWidth([_buttonNewTab frame]) + | 1016 CGRectGetWidth([_buttonNewTab frame]) + |
| 1123 kNewTabOverlap; | 1017 kNewTabOverlap - kNewTabRightPadding - |
| 1124 if (IsCompactTablet()) { | 1018 kTabSwitcherButtonWidth; |
| 1125 if ([self hasModeToggleSwitch]) | |
| 1126 availableSpace -= kNewTabRightPadding + kModeToggleButtonWidth; | |
| 1127 else | |
| 1128 availableSpace -= kNewTabRightPadding; | |
| 1129 } else { | |
| 1130 if (![self hasModeToggleSwitch]) | |
| 1131 availableSpace -= kNewTabRightPadding; | |
| 1132 } | |
| 1133 return availableSpace; | 1019 return availableSpace; |
| 1134 } | 1020 } |
| 1135 | 1021 |
| 1136 - (void)installTabSwitcherToggleButton { | 1022 - (void)installTabSwitcherButton { |
| 1137 // Add the mode toggle button view. | 1023 DCHECK(!_tabSwitcherButton); |
| 1138 DCHECK(!_tabSwitcherToggleButton); | 1024 UIImage* tabSwitcherButtonIcon = |
| 1139 UIImage* tabSwitcherToggleIcon = | |
| 1140 [UIImage imageNamed:@"tabswitcher_tab_switcher_button"]; | 1025 [UIImage imageNamed:@"tabswitcher_tab_switcher_button"]; |
| 1141 tabSwitcherToggleIcon = [tabSwitcherToggleIcon | 1026 tabSwitcherButtonIcon = [tabSwitcherButtonIcon |
| 1142 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | 1027 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
| 1143 int tabSwitcherToggleIdsAccessibilityLabel = | 1028 int tabSwitcherButtonIdsAccessibilityLabel = |
| 1144 IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER; | 1029 IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER; |
| 1145 NSString* tabSwitcherToggleEnglishUiAutomationName = @"Enter Tab Switcher"; | 1030 NSString* tabSwitcherButtonEnglishUiAutomationName = @"Enter Tab Switcher"; |
| 1146 const CGFloat tabStripHeight = _view.frame.size.height; | 1031 const CGFloat tabStripHeight = _view.frame.size.height; |
| 1147 CGRect buttonFrame = | 1032 CGRect buttonFrame = |
| 1148 CGRectMake(CGRectGetMaxX(_view.frame) - kTabSwitcherToggleButtonWidth, | 1033 CGRectMake(CGRectGetMaxX(_view.frame) - kTabSwitcherButtonWidth, 0.0, |
| 1149 0.0, kTabSwitcherToggleButtonWidth, tabStripHeight); | 1034 kTabSwitcherButtonWidth, tabStripHeight); |
| 1150 _tabSwitcherToggleButton = [UIButton buttonWithType:UIButtonTypeCustom]; | 1035 _tabSwitcherButton.reset( |
| 1151 [_tabSwitcherToggleButton setTintColor:[UIColor whiteColor]]; | 1036 [[UIButton buttonWithType:UIButtonTypeCustom] retain]); |
| 1152 _tabSwitcherToggleButton.frame = buttonFrame; | 1037 [_tabSwitcherButton setTintColor:[UIColor whiteColor]]; |
| 1153 [_tabSwitcherToggleButton setContentMode:UIViewContentModeCenter]; | 1038 [_tabSwitcherButton setFrame:buttonFrame]; |
| 1154 _tabSwitcherToggleButton.autoresizingMask = | 1039 [_tabSwitcherButton setContentMode:UIViewContentModeCenter]; |
| 1155 UIViewAutoresizingFlexibleLeftMargin; | 1040 [_tabSwitcherButton setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; |
| 1156 _tabSwitcherToggleButton.backgroundColor = [UIColor clearColor]; | 1041 [_tabSwitcherButton setBackgroundColor:[UIColor clearColor]]; |
| 1157 _tabSwitcherToggleButton.exclusiveTouch = YES; | 1042 [_tabSwitcherButton setExclusiveTouch:YES]; |
| 1158 [_tabSwitcherToggleButton setImage:tabSwitcherToggleIcon | 1043 [_tabSwitcherButton setImage:tabSwitcherButtonIcon |
| 1159 forState:UIControlStateNormal]; | 1044 forState:UIControlStateNormal]; |
| 1160 // Set target/action to bubble up with command id as tag. | 1045 // Set target/action to bubble up with command id as tag. |
| 1161 [_tabSwitcherToggleButton addTarget:nil | 1046 [_tabSwitcherButton addTarget:nil |
| 1162 action:@selector(chromeExecuteCommand:) | 1047 action:@selector(chromeExecuteCommand:) |
| 1163 forControlEvents:UIControlEventTouchUpInside]; | 1048 forControlEvents:UIControlEventTouchUpInside]; |
| 1164 [_tabSwitcherToggleButton setTag:IDC_TOGGLE_TAB_SWITCHER]; | 1049 [_tabSwitcherButton setTag:IDC_TOGGLE_TAB_SWITCHER]; |
| 1165 [_tabSwitcherToggleButton addTarget:self | 1050 [_tabSwitcherButton addTarget:self |
| 1166 action:@selector(recordUserMetrics:) | 1051 action:@selector(recordUserMetrics:) |
| 1167 forControlEvents:UIControlEventTouchUpInside]; | 1052 forControlEvents:UIControlEventTouchUpInside]; |
| 1168 | 1053 |
| 1169 SetA11yLabelAndUiAutomationName(_tabSwitcherToggleButton, | 1054 SetA11yLabelAndUiAutomationName(_tabSwitcherButton, |
| 1170 tabSwitcherToggleIdsAccessibilityLabel, | 1055 tabSwitcherButtonIdsAccessibilityLabel, |
| 1171 tabSwitcherToggleEnglishUiAutomationName); | 1056 tabSwitcherButtonEnglishUiAutomationName); |
| 1172 [_view addSubview:_tabSwitcherToggleButton]; | 1057 [_view addSubview:_tabSwitcherButton]; |
| 1173 // Shrink the scroll view. | 1058 // Shrink the scroll view. |
| 1174 [self updateScrollViewFrameForToggleButton]; | 1059 [self updateScrollViewFrameForTabSwitcherButton]; |
| 1175 } | |
| 1176 | |
| 1177 - (void)removeTabSwitcherToggleButton { | |
| 1178 // Remove the button view. | |
| 1179 DCHECK(_tabSwitcherToggleButton); | |
| 1180 [_tabSwitcherToggleButton removeFromSuperview]; | |
| 1181 _tabSwitcherToggleButton = nil; | |
| 1182 // Extend the scroll view. | |
| 1183 [self updateScrollViewFrameForToggleButton]; | |
| 1184 } | 1060 } |
| 1185 | 1061 |
| 1186 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset { | 1062 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset { |
| 1187 CGFloat dx = [_tabStripView contentOffset].x - oldContentOffset.x; | 1063 CGFloat dx = [_tabStripView contentOffset].x - oldContentOffset.x; |
| 1188 for (UIView* view in [_tabStripView subviews]) { | 1064 for (UIView* view in [_tabStripView subviews]) { |
| 1189 CGRect frame = [view frame]; | 1065 CGRect frame = [view frame]; |
| 1190 frame.origin.x += dx; | 1066 frame.origin.x += dx; |
| 1191 [view setFrame:frame]; | 1067 [view setFrame:frame]; |
| 1192 _targetFrames.AddFrame(view, frame); | 1068 _targetFrames.AddFrame(view, frame); |
| 1193 } | 1069 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 } else { | 1215 } else { |
| 1340 TabView* tabView = [_tabArray objectAtIndex:tabIndex]; | 1216 TabView* tabView = [_tabArray objectAtIndex:tabIndex]; |
| 1341 CGRect scrollRect = | 1217 CGRect scrollRect = |
| 1342 CGRectInset(tabView.frame, -_tabStripView.contentInset.right, 0); | 1218 CGRectInset(tabView.frame, -_tabStripView.contentInset.right, 0); |
| 1343 if (tabView) | 1219 if (tabView) |
| 1344 [_tabStripView scrollRectToVisible:scrollRect animated:YES]; | 1220 [_tabStripView scrollRectToVisible:scrollRect animated:YES]; |
| 1345 } | 1221 } |
| 1346 } | 1222 } |
| 1347 } | 1223 } |
| 1348 | 1224 |
| 1349 - (void)updateScrollViewFrameForToggleButton { | 1225 - (void)updateScrollViewFrameForTabSwitcherButton { |
| 1350 CGRect tabFrame = _tabStripView.frame; | 1226 CGRect tabFrame = _tabStripView.frame; |
| 1351 tabFrame.size.width = _view.bounds.size.width; | 1227 tabFrame.size.width = _view.bounds.size.width; |
| 1352 if (!IsCompactTablet()) { | 1228 if (!IsCompactTablet()) { |
| 1353 if (_modeToggleButton) | 1229 tabFrame.size.width -= kTabSwitcherButtonWidth; |
| 1354 tabFrame.size.width -= kModeToggleButtonWidth; | |
| 1355 if (_tabSwitcherToggleButton) | |
| 1356 tabFrame.size.width -= kTabSwitcherToggleButtonWidth; | |
| 1357 _tabStripView.contentInset = UIEdgeInsetsZero; | 1230 _tabStripView.contentInset = UIEdgeInsetsZero; |
| 1358 [_toggleButtonBackgroundView setHidden:YES]; | 1231 [_tabSwitcherButtonBackgroundView setHidden:YES]; |
| 1359 } else { | 1232 } else { |
| 1360 if (!_toggleButtonBackgroundView) { | 1233 if (!_tabSwitcherButtonBackgroundView) { |
| 1361 _toggleButtonBackgroundView.reset([[UIImageView alloc] init]); | 1234 _tabSwitcherButtonBackgroundView.reset([[UIImageView alloc] init]); |
| 1362 const CGFloat tabStripHeight = _view.frame.size.height; | 1235 const CGFloat tabStripHeight = _view.frame.size.height; |
| 1363 const CGRect backgroundViewFrame = CGRectMake( | 1236 const CGRect backgroundViewFrame = CGRectMake( |
| 1364 CGRectGetMaxX(_view.frame) - kModeToggleButtonBackgroundWidth, 0.0, | 1237 CGRectGetMaxX(_view.frame) - kTabSwitcherButtonBackgroundWidth, 0.0, |
| 1365 kModeToggleButtonBackgroundWidth, tabStripHeight); | 1238 kTabSwitcherButtonBackgroundWidth, tabStripHeight); |
| 1366 [_toggleButtonBackgroundView setFrame:backgroundViewFrame]; | 1239 [_tabSwitcherButtonBackgroundView setFrame:backgroundViewFrame]; |
| 1367 [_toggleButtonBackgroundView | 1240 [_tabSwitcherButtonBackgroundView |
| 1368 setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; | 1241 setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; |
| 1369 UIImage* backgroundToggleImage = | 1242 UIImage* backgroundTabSwitcherImage = |
| 1370 [UIImage imageNamed:@"tabstrip_toggle_button_gradient"]; | 1243 [UIImage imageNamed:@"tabstrip_toggle_button_gradient"]; |
| 1371 [_toggleButtonBackgroundView setImage:backgroundToggleImage]; | 1244 [_tabSwitcherButtonBackgroundView setImage:backgroundTabSwitcherImage]; |
| 1372 [_view addSubview:_toggleButtonBackgroundView]; | 1245 [_view addSubview:_tabSwitcherButtonBackgroundView]; |
| 1373 } | 1246 } |
| 1374 const BOOL hasModeToggleButton = | 1247 [_tabSwitcherButtonBackgroundView setHidden:NO]; |
| 1375 _modeToggleButton || _tabSwitcherToggleButton; | 1248 _tabStripView.contentInset = |
| 1376 [_toggleButtonBackgroundView setHidden:!hasModeToggleButton]; | 1249 UIEdgeInsetsMake(0, 0, 0, kTabSwitcherButtonWidth); |
| 1377 if (!hasModeToggleButton) | 1250 [_view bringSubviewToFront:_tabSwitcherButton]; |
| 1378 _tabStripView.contentInset = UIEdgeInsetsZero; | |
| 1379 if (_modeToggleButton) { | |
| 1380 _tabStripView.contentInset = | |
| 1381 UIEdgeInsetsMake(0, 0, 0, kModeToggleButtonWidth); | |
| 1382 [_view bringSubviewToFront:_modeToggleButton]; | |
| 1383 } | |
| 1384 if (_tabSwitcherToggleButton) { | |
| 1385 _tabStripView.contentInset = | |
| 1386 UIEdgeInsetsMake(0, 0, 0, kTabSwitcherToggleButtonWidth); | |
| 1387 [_view bringSubviewToFront:_tabSwitcherToggleButton]; | |
| 1388 } | |
| 1389 } | 1251 } |
| 1390 [_tabStripView setFrame:tabFrame]; | 1252 [_tabStripView setFrame:tabFrame]; |
| 1391 } | 1253 } |
| 1392 | 1254 |
| 1393 #pragma mark - TabStripViewLayoutDelegate | 1255 #pragma mark - TabStripViewLayoutDelegate |
| 1394 | 1256 |
| 1395 // Creates TabViews for each Tab in the TabModel and positions them in the | 1257 // Creates TabViews for each Tab in the TabModel and positions them in the |
| 1396 // correct location onscreen. | 1258 // correct location onscreen. |
| 1397 - (void)layoutTabStripSubviews { | 1259 - (void)layoutTabStripSubviews { |
| 1398 const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; | 1260 const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 [view setFrame:_targetFrames.GetFrame(view)]; | 1527 [view setFrame:_targetFrames.GetFrame(view)]; |
| 1666 } | 1528 } |
| 1667 if (moveNewTab) | 1529 if (moveNewTab) |
| 1668 [_buttonNewTab setFrame:newTabFrame]; | 1530 [_buttonNewTab setFrame:newTabFrame]; |
| 1669 } | 1531 } |
| 1670 completion:nil]; | 1532 completion:nil]; |
| 1671 } | 1533 } |
| 1672 } | 1534 } |
| 1673 | 1535 |
| 1674 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { | 1536 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { |
| 1675 [self updateScrollViewFrameForToggleButton]; | 1537 [self updateScrollViewFrameForTabSwitcherButton]; |
| 1676 [self updateContentSizeAndRepositionViews]; | 1538 [self updateContentSizeAndRepositionViews]; |
| 1677 NSUInteger selectedModelIndex = [_tabModel indexOfTab:[_tabModel currentTab]]; | 1539 NSUInteger selectedModelIndex = [_tabModel indexOfTab:[_tabModel currentTab]]; |
| 1678 if (selectedModelIndex != NSNotFound) { | 1540 if (selectedModelIndex != NSNotFound) { |
| 1679 [self updateContentOffsetForTabIndex:selectedModelIndex isNewTab:NO]; | 1541 [self updateContentOffsetForTabIndex:selectedModelIndex isNewTab:NO]; |
| 1680 } | 1542 } |
| 1681 } | 1543 } |
| 1682 | 1544 |
| 1683 - (void)setNeedsLayoutWithAnimation { | 1545 - (void)setNeedsLayoutWithAnimation { |
| 1684 _animateLayout = YES; | 1546 _animateLayout = YES; |
| 1685 [_tabStripView setNeedsLayout]; | 1547 [_tabStripView setNeedsLayout]; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 | 1592 |
| 1731 @implementation TabStripController (Testing) | 1593 @implementation TabStripController (Testing) |
| 1732 | 1594 |
| 1733 - (TabView*)existingTabViewForTab:(Tab*)tab { | 1595 - (TabView*)existingTabViewForTab:(Tab*)tab { |
| 1734 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; | 1596 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; |
| 1735 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; | 1597 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; |
| 1736 return [_tabArray objectAtIndex:tabViewIndex]; | 1598 return [_tabArray objectAtIndex:tabViewIndex]; |
| 1737 } | 1599 } |
| 1738 | 1600 |
| 1739 @end | 1601 @end |
| OLD | NEW |