| 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 |
| 11 #include "base/i18n/rtl.h" | 11 #include "base/i18n/rtl.h" |
| 12 #import "base/ios/weak_nsobject.h" | |
| 13 #include "base/mac/bundle_locations.h" | 12 #include "base/mac/bundle_locations.h" |
| 14 #include "base/mac/foundation_util.h" | 13 #include "base/mac/foundation_util.h" |
| 15 #include "base/mac/objc_property_releaser.h" | 14 |
| 16 #include "base/mac/scoped_nsobject.h" | |
| 17 #include "base/metrics/user_metrics.h" | 15 #include "base/metrics/user_metrics.h" |
| 18 #include "base/metrics/user_metrics_action.h" | 16 #include "base/metrics/user_metrics_action.h" |
| 19 #include "base/strings/sys_string_conversions.h" | 17 #include "base/strings/sys_string_conversions.h" |
| 20 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 18 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 21 #include "ios/chrome/browser/experimental_flags.h" | 19 #include "ios/chrome/browser/experimental_flags.h" |
| 22 #import "ios/chrome/browser/tabs/tab.h" | 20 #import "ios/chrome/browser/tabs/tab.h" |
| 23 #import "ios/chrome/browser/tabs/tab_model.h" | 21 #import "ios/chrome/browser/tabs/tab_model.h" |
| 24 #import "ios/chrome/browser/tabs/tab_model_observer.h" | 22 #import "ios/chrome/browser/tabs/tab_model_observer.h" |
| 25 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" | 23 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" |
| 26 #include "ios/chrome/browser/ui/commands/ios_command_ids.h" | 24 #include "ios/chrome/browser/ui/commands/ios_command_ids.h" |
| 27 #import "ios/chrome/browser/ui/fullscreen_controller.h" | 25 #import "ios/chrome/browser/ui/fullscreen_controller.h" |
| 28 #include "ios/chrome/browser/ui/rtl_geometry.h" | 26 #include "ios/chrome/browser/ui/rtl_geometry.h" |
| 29 #include "ios/chrome/browser/ui/tab_switcher/tab_switcher_tab_strip_placeholder_
view.h" | 27 #include "ios/chrome/browser/ui/tab_switcher/tab_switcher_tab_strip_placeholder_
view.h" |
| 30 #import "ios/chrome/browser/ui/tabs/tab_strip_controller+tab_switcher_animation.
h" | 28 #import "ios/chrome/browser/ui/tabs/tab_strip_controller+tab_switcher_animation.
h" |
| 31 #import "ios/chrome/browser/ui/tabs/tab_strip_view.h" | 29 #import "ios/chrome/browser/ui/tabs/tab_strip_view.h" |
| 32 #import "ios/chrome/browser/ui/tabs/tab_view.h" | 30 #import "ios/chrome/browser/ui/tabs/tab_view.h" |
| 33 #include "ios/chrome/browser/ui/tabs/target_frame_cache.h" | 31 #include "ios/chrome/browser/ui/tabs/target_frame_cache.h" |
| 34 #include "ios/chrome/browser/ui/ui_util.h" | 32 #include "ios/chrome/browser/ui/ui_util.h" |
| 35 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 33 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
| 36 #import "ios/chrome/browser/ui/util/snapshot_util.h" | 34 #import "ios/chrome/browser/ui/util/snapshot_util.h" |
| 37 #include "ios/chrome/grit/ios_strings.h" | 35 #include "ios/chrome/grit/ios_strings.h" |
| 38 #import "ios/web/public/web_state/web_state.h" | 36 #import "ios/web/public/web_state/web_state.h" |
| 39 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h
" | 37 #include "third_party/google_toolbox_for_mac/src/iPhone/GTMFadeTruncatingLabel.h
" |
| 40 #include "ui/gfx/image/image.h" | 38 #include "ui/gfx/image/image.h" |
| 41 | 39 |
| 40 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 41 #error "This file requires ARC support." |
| 42 #endif |
| 43 |
| 42 using base::UserMetricsAction; | 44 using base::UserMetricsAction; |
| 43 | 45 |
| 44 NSString* const kWillStartTabStripTabAnimation = | 46 NSString* const kWillStartTabStripTabAnimation = |
| 45 @"kWillStartTabStripTabAnimation"; | 47 @"kWillStartTabStripTabAnimation"; |
| 46 NSString* const kTabStripDragStarted = @"kTabStripDragStarted"; | 48 NSString* const kTabStripDragStarted = @"kTabStripDragStarted"; |
| 47 NSString* const kTabStripDragEnded = @"kTabStripDragEnded"; | 49 NSString* const kTabStripDragEnded = @"kTabStripDragEnded"; |
| 48 | 50 |
| 49 namespace TabStrip { | 51 namespace TabStrip { |
| 50 UIColor* BackgroundColor() { | 52 UIColor* BackgroundColor() { |
| 51 DCHECK(IsIPadIdiom()); | 53 DCHECK(IsIPadIdiom()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 113 |
| 112 // Offsets needed to keep the UI properly centered on high-res screens, in | 114 // Offsets needed to keep the UI properly centered on high-res screens, in |
| 113 // points. | 115 // points. |
| 114 const CGFloat kNewTabButtonBottomOffsetHighRes = 2.0; | 116 const CGFloat kNewTabButtonBottomOffsetHighRes = 2.0; |
| 115 } | 117 } |
| 116 | 118 |
| 117 @interface TabStripController ()<TabModelObserver, | 119 @interface TabStripController ()<TabModelObserver, |
| 118 TabStripViewLayoutDelegate, | 120 TabStripViewLayoutDelegate, |
| 119 UIGestureRecognizerDelegate, | 121 UIGestureRecognizerDelegate, |
| 120 UIScrollViewDelegate> { | 122 UIScrollViewDelegate> { |
| 121 base::scoped_nsobject<TabModel> _tabModel; | 123 TabModel* _tabModel; |
| 122 UIView* _view; | 124 UIView* _view; |
| 123 TabStripView* _tabStripView; | 125 TabStripView* _tabStripView; |
| 124 UIButton* _buttonNewTab; | 126 UIButton* _buttonNewTab; |
| 125 base::scoped_nsobject<UIButton> _tabSwitcherButton; | 127 UIButton* _tabSwitcherButton; |
| 126 | 128 |
| 127 // Background view of the tab switcher button. Only visible while in compact | 129 // Background view of the tab switcher button. Only visible while in compact |
| 128 // layout. | 130 // layout. |
| 129 base::scoped_nsobject<UIImageView> _tabSwitcherButtonBackgroundView; | 131 UIImageView* _tabSwitcherButtonBackgroundView; |
| 130 | 132 |
| 131 TabStrip::Style _style; | 133 TabStrip::Style _style; |
| 132 base::WeakNSProtocol<id<FullScreenControllerDelegate>> _fullscreenDelegate; | 134 __weak id<FullScreenControllerDelegate> _fullscreenDelegate; |
| 133 | 135 |
| 134 // Array of TabViews. There is a one-to-one correspondence between this array | 136 // Array of TabViews. There is a one-to-one correspondence between this array |
| 135 // and the set of Tabs in the TabModel. | 137 // and the set of Tabs in the TabModel. |
| 136 base::scoped_nsobject<NSMutableArray> _tabArray; | 138 NSMutableArray* _tabArray; |
| 137 | 139 |
| 138 // Set of TabViews that are currently closing. These TabViews are also in | 140 // Set of TabViews that are currently closing. These TabViews are also in |
| 139 // |_tabArray|. Used to translate between |_tabArray| indexes and TabModel | 141 // |_tabArray|. Used to translate between |_tabArray| indexes and TabModel |
| 140 // indexes. | 142 // indexes. |
| 141 base::scoped_nsobject<NSMutableSet> _closingTabs; | 143 NSMutableSet* _closingTabs; |
| 142 | 144 |
| 143 // Tracks target frames for TabViews. | 145 // Tracks target frames for TabViews. |
| 144 // TODO(rohitrao): This is unnecessary, as UIKit updates view frames | 146 // TODO(rohitrao): This is unnecessary, as UIKit updates view frames |
| 145 // immediately, so [view frame] will always return the end state of the | 147 // immediately, so [view frame] will always return the end state of the |
| 146 // current animation. We can remove this cache entirely. b/5516053 | 148 // current animation. We can remove this cache entirely. b/5516053 |
| 147 TargetFrameCache _targetFrames; | 149 TargetFrameCache _targetFrames; |
| 148 | 150 |
| 149 // Animate when doing layout. This flag is set by setNeedsLayoutWithAnimation | 151 // Animate when doing layout. This flag is set by setNeedsLayoutWithAnimation |
| 150 // and cleared in layoutSubviews. | 152 // and cleared in layoutSubviews. |
| 151 BOOL _animateLayout; | 153 BOOL _animateLayout; |
| 152 | 154 |
| 153 // The current tab width. Recomputed whenever a tab is added or removed. | 155 // The current tab width. Recomputed whenever a tab is added or removed. |
| 154 CGFloat _currentTabWidth; | 156 CGFloat _currentTabWidth; |
| 155 | 157 |
| 156 // View used to dim unselected tabs when in reordering mode. Nil when not | 158 // View used to dim unselected tabs when in reordering mode. Nil when not |
| 157 // reordering tabs. | 159 // reordering tabs. |
| 158 base::scoped_nsobject<UIView> _dimmingView; | 160 UIView* _dimmingView; |
| 159 | 161 |
| 160 // Is the selected tab highlighted, used when dragging or swiping tabs. | 162 // Is the selected tab highlighted, used when dragging or swiping tabs. |
| 161 BOOL _highlightsSelectedTab; | 163 BOOL _highlightsSelectedTab; |
| 162 | 164 |
| 163 // YES when in reordering mode. | 165 // YES when in reordering mode. |
| 164 // TODO(rohitrao): This is redundant with |_draggedTab|. Remove it. | 166 // TODO(rohitrao): This is redundant with |_draggedTab|. Remove it. |
| 165 BOOL _isReordering; | 167 BOOL _isReordering; |
| 166 | 168 |
| 167 // The tab that is currently being dragged. nil when not in reordering mode. | 169 // The tab that is currently being dragged. nil when not in reordering mode. |
| 168 base::scoped_nsobject<TabView> _draggedTab; | 170 TabView* _draggedTab; |
| 169 | 171 |
| 170 // The last known location of the touch that is dragging the tab. This | 172 // The last known location of the touch that is dragging the tab. This |
| 171 // location is in the coordinate system of |[_tabStripView superview]| because | 173 // location is in the coordinate system of |[_tabStripView superview]| because |
| 172 // that coordinate system does not change as the scroll view scrolls. | 174 // that coordinate system does not change as the scroll view scrolls. |
| 173 CGPoint _lastDragLocation; | 175 CGPoint _lastDragLocation; |
| 174 | 176 |
| 175 // Timer used to autoscroll when in reordering mode. Is nil when not active. | 177 // Timer used to autoscroll when in reordering mode. Is nil when not active. |
| 176 // Owned by its runloop. | 178 // Owned by its runloop. |
| 177 NSTimer* _autoscrollTimer; // weak | 179 NSTimer* _autoscrollTimer; // weak |
| 178 | 180 |
| 179 // The distance to scroll for each autoscroll timer tick. If negative, the | 181 // The distance to scroll for each autoscroll timer tick. If negative, the |
| 180 // tabstrip will scroll to the left; if positive, to the right. | 182 // tabstrip will scroll to the left; if positive, to the right. |
| 181 CGFloat _autoscrollDistance; | 183 CGFloat _autoscrollDistance; |
| 182 | 184 |
| 183 // The model index of the placeholder gap, if one exists. This value is used | 185 // The model index of the placeholder gap, if one exists. This value is used |
| 184 // as the new model index of the dragged tab when it is dropped. | 186 // as the new model index of the dragged tab when it is dropped. |
| 185 NSUInteger _placeholderGapModelIndex; | 187 NSUInteger _placeholderGapModelIndex; |
| 186 | |
| 187 base::mac::ObjCPropertyReleaser _propertyReleaser_TabStripController; | |
| 188 } | 188 } |
| 189 | 189 |
| 190 @property(nonatomic, readonly, retain) TabStripView* tabStripView; | 190 @property(nonatomic, readonly, retain) TabStripView* tabStripView; |
| 191 @property(nonatomic, readonly, retain) UIButton* buttonNewTab; | 191 @property(nonatomic, readonly, retain) UIButton* buttonNewTab; |
| 192 | 192 |
| 193 // 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 |
| 194 // 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 |
| 195 // |-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. |
| 196 - (void)initializeTabArrayFromTabModel; | 196 - (void)initializeTabArrayFromTabModel; |
| 197 | 197 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 @implementation TabStripController | 319 @implementation TabStripController |
| 320 | 320 |
| 321 @synthesize buttonNewTab = _buttonNewTab; | 321 @synthesize buttonNewTab = _buttonNewTab; |
| 322 @synthesize highlightsSelectedTab = _highlightsSelectedTab; | 322 @synthesize highlightsSelectedTab = _highlightsSelectedTab; |
| 323 @synthesize tabStripView = _tabStripView; | 323 @synthesize tabStripView = _tabStripView; |
| 324 @synthesize view = _view; | 324 @synthesize view = _view; |
| 325 | 325 |
| 326 - (instancetype)initWithTabModel:(TabModel*)tabModel | 326 - (instancetype)initWithTabModel:(TabModel*)tabModel |
| 327 style:(TabStrip::Style)style { | 327 style:(TabStrip::Style)style { |
| 328 if ((self = [super init])) { | 328 if ((self = [super init])) { |
| 329 _propertyReleaser_TabStripController.Init(self, [TabStripController class]); | 329 _tabArray = [[NSMutableArray alloc] initWithCapacity:10]; |
| 330 _tabArray.reset([[NSMutableArray alloc] initWithCapacity:10]); | 330 _closingTabs = [[NSMutableSet alloc] initWithCapacity:5]; |
| 331 _closingTabs.reset([[NSMutableSet alloc] initWithCapacity:5]); | |
| 332 | 331 |
| 333 _tabModel.reset([tabModel retain]); | 332 _tabModel = tabModel; |
| 334 [_tabModel addObserver:self]; | 333 [_tabModel addObserver:self]; |
| 335 _style = style; | 334 _style = style; |
| 336 | 335 |
| 337 // |self.view| setup. | 336 // |self.view| setup. |
| 338 CGRect tabStripFrame = [UIApplication sharedApplication].keyWindow.bounds; | 337 CGRect tabStripFrame = [UIApplication sharedApplication].keyWindow.bounds; |
| 339 tabStripFrame.size.height = kTabStripHeight; | 338 tabStripFrame.size.height = kTabStripHeight; |
| 340 _view = [[UIView alloc] initWithFrame:tabStripFrame]; | 339 _view = [[UIView alloc] initWithFrame:tabStripFrame]; |
| 341 _view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | | 340 _view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | |
| 342 UIViewAutoresizingFlexibleBottomMargin); | 341 UIViewAutoresizingFlexibleBottomMargin); |
| 343 _view.backgroundColor = TabStrip::BackgroundColor(); | 342 _view.backgroundColor = TabStrip::BackgroundColor(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 | 424 |
| 426 - (instancetype)init { | 425 - (instancetype)init { |
| 427 NOTREACHED(); | 426 NOTREACHED(); |
| 428 return nil; | 427 return nil; |
| 429 } | 428 } |
| 430 | 429 |
| 431 - (void)dealloc { | 430 - (void)dealloc { |
| 432 [_tabStripView setDelegate:nil]; | 431 [_tabStripView setDelegate:nil]; |
| 433 [_tabStripView setLayoutDelegate:nil]; | 432 [_tabStripView setLayoutDelegate:nil]; |
| 434 [_tabModel removeObserver:self]; | 433 [_tabModel removeObserver:self]; |
| 435 [super dealloc]; | |
| 436 } | 434 } |
| 437 | 435 |
| 438 - (id<FullScreenControllerDelegate>)fullscreenDelegate { | 436 - (id<FullScreenControllerDelegate>)fullscreenDelegate { |
| 439 return _fullscreenDelegate; | 437 return _fullscreenDelegate; |
| 440 } | 438 } |
| 441 | 439 |
| 442 - (void)setFullscreenDelegate: | 440 - (void)setFullscreenDelegate: |
| 443 (id<FullScreenControllerDelegate>)fullscreenDelegate { | 441 (id<FullScreenControllerDelegate>)fullscreenDelegate { |
| 444 _fullscreenDelegate.reset(fullscreenDelegate); | 442 _fullscreenDelegate = fullscreenDelegate; |
| 445 } | 443 } |
| 446 | 444 |
| 447 - (void)initializeTabArrayFromTabModel { | 445 - (void)initializeTabArrayFromTabModel { |
| 448 DCHECK(_tabModel); | 446 DCHECK(_tabModel); |
| 449 for (Tab* tab in _tabModel.get()) { | 447 for (Tab* tab in _tabModel) { |
| 450 BOOL isSelectedTab = [_tabModel currentTab] == tab; | 448 BOOL isSelectedTab = [_tabModel currentTab] == tab; |
| 451 TabView* view = [self tabViewForTab:tab isSelected:isSelectedTab]; | 449 TabView* view = [self tabViewForTab:tab isSelected:isSelectedTab]; |
| 452 [_tabArray addObject:view]; | 450 [_tabArray addObject:view]; |
| 453 [_tabStripView addSubview:view]; | 451 [_tabStripView addSubview:view]; |
| 454 } | 452 } |
| 455 } | 453 } |
| 456 | 454 |
| 457 - (void)initializeTabArrayWithNoModel { | 455 - (void)initializeTabArrayWithNoModel { |
| 458 DCHECK(!_tabModel); | 456 DCHECK(!_tabModel); |
| 459 TabView* view = [self emptyTabView]; | 457 TabView* view = [self emptyTabView]; |
| 460 [_tabArray addObject:view]; | 458 [_tabArray addObject:view]; |
| 461 [_tabStripView addSubview:view]; | 459 [_tabStripView addSubview:view]; |
| 462 [view setSelected:YES]; | 460 [view setSelected:YES]; |
| 463 return; | 461 return; |
| 464 } | 462 } |
| 465 | 463 |
| 466 - (TabView*)emptyTabView { | 464 - (TabView*)emptyTabView { |
| 467 TabView* view = | 465 TabView* view = [[TabView alloc] initWithEmptyView:YES selected:YES]; |
| 468 [[[TabView alloc] initWithEmptyView:YES selected:YES] autorelease]; | |
| 469 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; | 466 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; |
| 470 [view setContentMode:UIViewContentModeRedraw]; | 467 [view setContentMode:UIViewContentModeRedraw]; |
| 471 | 468 |
| 472 // Setting the tab to be hidden marks it as a new tab. The layout code will | 469 // Setting the tab to be hidden marks it as a new tab. The layout code will |
| 473 // make the tab visible and set up the appropriate animations. | 470 // make the tab visible and set up the appropriate animations. |
| 474 [view setHidden:YES]; | 471 [view setHidden:YES]; |
| 475 | 472 |
| 476 return view; | 473 return view; |
| 477 } | 474 } |
| 478 | 475 |
| 479 - (TabView*)tabViewForTab:(Tab*)tab isSelected:(BOOL)isSelected { | 476 - (TabView*)tabViewForTab:(Tab*)tab isSelected:(BOOL)isSelected { |
| 480 TabView* view = | 477 TabView* view = [[TabView alloc] initWithEmptyView:NO selected:isSelected]; |
| 481 [[[TabView alloc] initWithEmptyView:NO selected:isSelected] autorelease]; | |
| 482 if (UseRTLLayout()) | 478 if (UseRTLLayout()) |
| 483 [view setTransform:CGAffineTransformMakeScale(-1, 1)]; | 479 [view setTransform:CGAffineTransformMakeScale(-1, 1)]; |
| 484 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; | 480 [view setIncognitoStyle:(_style == TabStrip::kStyleIncognito)]; |
| 485 [view setContentMode:UIViewContentModeRedraw]; | 481 [view setContentMode:UIViewContentModeRedraw]; |
| 486 [[view titleLabel] setText:[tab title]]; | 482 [[view titleLabel] setText:[tab title]]; |
| 487 [view setFavicon:[tab favicon]]; | 483 [view setFavicon:[tab favicon]]; |
| 488 | 484 |
| 489 // Set the tab buttons' action messages. | 485 // Set the tab buttons' action messages. |
| 490 [view addTarget:self | 486 [view addTarget:self |
| 491 action:@selector(tabTapped:) | 487 action:@selector(tabTapped:) |
| 492 forControlEvents:UIControlEventTouchUpInside]; | 488 forControlEvents:UIControlEventTouchUpInside]; |
| 493 [[view closeButton] addTarget:self | 489 [[view closeButton] addTarget:self |
| 494 action:@selector(closeTab:) | 490 action:@selector(closeTab:) |
| 495 forControlEvents:UIControlEventTouchUpInside]; | 491 forControlEvents:UIControlEventTouchUpInside]; |
| 496 | 492 |
| 497 // Install a long press gesture recognizer to handle drag and drop. | 493 // Install a long press gesture recognizer to handle drag and drop. |
| 498 base::scoped_nsobject<UILongPressGestureRecognizer> longPress( | 494 UILongPressGestureRecognizer* longPress = |
| 499 [[UILongPressGestureRecognizer alloc] | 495 [[UILongPressGestureRecognizer alloc] |
| 500 initWithTarget:self | 496 initWithTarget:self |
| 501 action:@selector(handleLongPress:)]); | 497 action:@selector(handleLongPress:)]; |
| 502 [longPress setMinimumPressDuration:kDragAndDropLongPressDuration]; | 498 [longPress setMinimumPressDuration:kDragAndDropLongPressDuration]; |
| 503 [longPress setDelegate:self]; | 499 [longPress setDelegate:self]; |
| 504 [view addGestureRecognizer:longPress]; | 500 [view addGestureRecognizer:longPress]; |
| 505 | 501 |
| 506 // Giving the tab view exclusive touch prevents other views from receiving | 502 // Giving the tab view exclusive touch prevents other views from receiving |
| 507 // touches while a TabView is handling a touch. | 503 // touches while a TabView is handling a touch. |
| 508 [view setExclusiveTouch:YES]; | 504 [view setExclusiveTouch:YES]; |
| 509 | 505 |
| 510 // Setting the tab to be hidden marks it as a new tab. The layout code will | 506 // Setting the tab to be hidden marks it as a new tab. The layout code will |
| 511 // make the tab visible and set up the appropriate animations. | 507 // make the tab visible and set up the appropriate animations. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 526 - (void)installDimmingViewWithAnimation:(BOOL)animate { | 522 - (void)installDimmingViewWithAnimation:(BOOL)animate { |
| 527 // The dimming view should not cover the bottom 2px of the tab strip, as those | 523 // The dimming view should not cover the bottom 2px of the tab strip, as those |
| 528 // pixels are visually part of the top border of the toolbar. The bottom | 524 // pixels are visually part of the top border of the toolbar. The bottom |
| 529 // inset constants take into account the conversion from pixels to points. | 525 // inset constants take into account the conversion from pixels to points. |
| 530 CGRect frame = [_tabStripView bounds]; | 526 CGRect frame = [_tabStripView bounds]; |
| 531 frame.size.height -= (IsHighResScreen() ? kDimmingViewBottomInsetHighRes | 527 frame.size.height -= (IsHighResScreen() ? kDimmingViewBottomInsetHighRes |
| 532 : kDimmingViewBottomInset); | 528 : kDimmingViewBottomInset); |
| 533 | 529 |
| 534 // Create the dimming view if it doesn't exist. In all cases, make sure it's | 530 // Create the dimming view if it doesn't exist. In all cases, make sure it's |
| 535 // set up correctly. | 531 // set up correctly. |
| 536 if (_dimmingView.get()) | 532 if (_dimmingView) |
| 537 [_dimmingView setFrame:frame]; | 533 [_dimmingView setFrame:frame]; |
| 538 else | 534 else |
| 539 _dimmingView.reset([[UIView alloc] initWithFrame:frame]); | 535 _dimmingView = [[UIView alloc] initWithFrame:frame]; |
| 540 | 536 |
| 541 // Enable user interaction in order to eat touches from views behind it. | 537 // Enable user interaction in order to eat touches from views behind it. |
| 542 [_dimmingView setUserInteractionEnabled:YES]; | 538 [_dimmingView setUserInteractionEnabled:YES]; |
| 543 [_dimmingView setBackgroundColor:[TabStrip::BackgroundColor() | 539 [_dimmingView setBackgroundColor:[TabStrip::BackgroundColor() |
| 544 colorWithAlphaComponent:0]]; | 540 colorWithAlphaComponent:0]]; |
| 545 [_dimmingView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | | 541 [_dimmingView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | |
| 546 UIViewAutoresizingFlexibleHeight)]; | 542 UIViewAutoresizingFlexibleHeight)]; |
| 547 [_tabStripView addSubview:_dimmingView]; | 543 [_tabStripView addSubview:_dimmingView]; |
| 548 | 544 |
| 549 CGFloat duration = animate ? kTabStripFadeAnimationDuration : 0; | 545 CGFloat duration = animate ? kTabStripFadeAnimationDuration : 0; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 560 CGFloat duration = animate ? kTabStripFadeAnimationDuration : 0; | 556 CGFloat duration = animate ? kTabStripFadeAnimationDuration : 0; |
| 561 [UIView animateWithDuration:duration | 557 [UIView animateWithDuration:duration |
| 562 animations:^{ | 558 animations:^{ |
| 563 [_dimmingView setBackgroundColor:[TabStrip::BackgroundColor() | 559 [_dimmingView setBackgroundColor:[TabStrip::BackgroundColor() |
| 564 colorWithAlphaComponent:0]]; | 560 colorWithAlphaComponent:0]]; |
| 565 } | 561 } |
| 566 completion:^(BOOL finished) { | 562 completion:^(BOOL finished) { |
| 567 // Do not remove the dimming view if the animation was aborted. | 563 // Do not remove the dimming view if the animation was aborted. |
| 568 if (finished) { | 564 if (finished) { |
| 569 [_dimmingView removeFromSuperview]; | 565 [_dimmingView removeFromSuperview]; |
| 570 _dimmingView.reset(); | 566 _dimmingView = nil; |
| 571 } | 567 } |
| 572 }]; | 568 }]; |
| 573 } | 569 } |
| 574 } | 570 } |
| 575 | 571 |
| 576 - (void)recordUserMetrics:(id)sender { | 572 - (void)recordUserMetrics:(id)sender { |
| 577 if (sender == _buttonNewTab) | 573 if (sender == _buttonNewTab) |
| 578 base::RecordAction(UserMetricsAction("MobileTabStripNewTab")); | 574 base::RecordAction(UserMetricsAction("MobileTabStripNewTab")); |
| 579 else if (sender == _tabSwitcherButton.get()) | 575 else if (sender == _tabSwitcherButton) |
| 580 base::RecordAction(UserMetricsAction("MobileTabSwitcherOpen")); | 576 base::RecordAction(UserMetricsAction("MobileTabSwitcherOpen")); |
| 581 else | 577 else |
| 582 LOG(WARNING) << "Trying to record metrics for unknown sender " | 578 LOG(WARNING) << "Trying to record metrics for unknown sender " |
| 583 << base::SysNSStringToUTF8([sender description]); | 579 << base::SysNSStringToUTF8([sender description]); |
| 584 } | 580 } |
| 585 | 581 |
| 586 - (void)tabTapped:(id)sender { | 582 - (void)tabTapped:(id)sender { |
| 587 DCHECK([sender isKindOfClass:[TabView class]]); | 583 DCHECK([sender isKindOfClass:[TabView class]]); |
| 588 | 584 |
| 589 // Ignore taps while in reordering mode. | 585 // Ignore taps while in reordering mode. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 object:nil]; | 639 object:nil]; |
| 644 break; | 640 break; |
| 645 default: | 641 default: |
| 646 NOTREACHED(); | 642 NOTREACHED(); |
| 647 } | 643 } |
| 648 } | 644 } |
| 649 | 645 |
| 650 - (NSUInteger)indexForModelIndex:(NSUInteger)modelIndex { | 646 - (NSUInteger)indexForModelIndex:(NSUInteger)modelIndex { |
| 651 NSUInteger index = modelIndex; | 647 NSUInteger index = modelIndex; |
| 652 NSUInteger i = 0; | 648 NSUInteger i = 0; |
| 653 for (TabView* tab in _tabArray.get()) { | 649 for (TabView* tab in _tabArray) { |
| 654 if ([_closingTabs containsObject:tab]) | 650 if ([_closingTabs containsObject:tab]) |
| 655 ++index; | 651 ++index; |
| 656 | 652 |
| 657 if (i == index) | 653 if (i == index) |
| 658 break; | 654 break; |
| 659 | 655 |
| 660 ++i; | 656 ++i; |
| 661 } | 657 } |
| 662 | 658 |
| 663 DCHECK_GE(index, modelIndex); | 659 DCHECK_GE(index, modelIndex); |
| 664 return index; | 660 return index; |
| 665 } | 661 } |
| 666 | 662 |
| 667 - (NSUInteger)modelIndexForIndex:(NSUInteger)index { | 663 - (NSUInteger)modelIndexForIndex:(NSUInteger)index { |
| 668 NSUInteger modelIndex = 0; | 664 NSUInteger modelIndex = 0; |
| 669 NSUInteger arrayIndex = 0; | 665 NSUInteger arrayIndex = 0; |
| 670 for (TabView* tab in _tabArray.get()) { | 666 for (TabView* tab in _tabArray) { |
| 671 if (arrayIndex == index) { | 667 if (arrayIndex == index) { |
| 672 if ([_closingTabs containsObject:tab]) | 668 if ([_closingTabs containsObject:tab]) |
| 673 return NSNotFound; | 669 return NSNotFound; |
| 674 return modelIndex; | 670 return modelIndex; |
| 675 } | 671 } |
| 676 | 672 |
| 677 if (![_closingTabs containsObject:tab]) | 673 if (![_closingTabs containsObject:tab]) |
| 678 ++modelIndex; | 674 ++modelIndex; |
| 679 | 675 |
| 680 ++arrayIndex; | 676 ++arrayIndex; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 703 // Install the dimming view, hide the new tab button, and select the tab so it | 699 // Install the dimming view, hide the new tab button, and select the tab so it |
| 704 // appears highlighted. | 700 // appears highlighted. |
| 705 Tab* tab = [_tabModel tabAtIndex:index]; | 701 Tab* tab = [_tabModel tabAtIndex:index]; |
| 706 self.highlightsSelectedTab = YES; | 702 self.highlightsSelectedTab = YES; |
| 707 _buttonNewTab.hidden = YES; | 703 _buttonNewTab.hidden = YES; |
| 708 [_tabModel setCurrentTab:tab]; | 704 [_tabModel setCurrentTab:tab]; |
| 709 | 705 |
| 710 // Set up initial drag state. | 706 // Set up initial drag state. |
| 711 _lastDragLocation = [gesture locationInView:[_tabStripView superview]]; | 707 _lastDragLocation = [gesture locationInView:[_tabStripView superview]]; |
| 712 _isReordering = YES; | 708 _isReordering = YES; |
| 713 _draggedTab.reset([view retain]); | 709 _draggedTab = view; |
| 714 _placeholderGapModelIndex = [self modelIndexForTabView:_draggedTab]; | 710 _placeholderGapModelIndex = [self modelIndexForTabView:_draggedTab]; |
| 715 | 711 |
| 716 // Update the autoscroll distance and timer. | 712 // Update the autoscroll distance and timer. |
| 717 [self computeAutoscrollDistanceForTabView:_draggedTab]; | 713 [self computeAutoscrollDistanceForTabView:_draggedTab]; |
| 718 if (_autoscrollDistance != 0) | 714 if (_autoscrollDistance != 0) |
| 719 [self installAutoscrollTimerIfNeeded]; | 715 [self installAutoscrollTimerIfNeeded]; |
| 720 else | 716 else |
| 721 [self removeAutoscrollTimer]; | 717 [self removeAutoscrollTimer]; |
| 722 } | 718 } |
| 723 | 719 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 [self setNeedsLayoutWithAnimation]; | 774 [self setNeedsLayoutWithAnimation]; |
| 779 } | 775 } |
| 780 | 776 |
| 781 - (void)resetDragState { | 777 - (void)resetDragState { |
| 782 self.highlightsSelectedTab = NO; | 778 self.highlightsSelectedTab = NO; |
| 783 _buttonNewTab.hidden = NO; | 779 _buttonNewTab.hidden = NO; |
| 784 [self removeAutoscrollTimer]; | 780 [self removeAutoscrollTimer]; |
| 785 | 781 |
| 786 _isReordering = NO; | 782 _isReordering = NO; |
| 787 _placeholderGapModelIndex = NSNotFound; | 783 _placeholderGapModelIndex = NSNotFound; |
| 788 _draggedTab.reset(); | 784 _draggedTab = nil; |
| 789 } | 785 } |
| 790 | 786 |
| 791 - (BOOL)isReorderingTabs { | 787 - (BOOL)isReorderingTabs { |
| 792 return _isReordering; | 788 return _isReordering; |
| 793 } | 789 } |
| 794 | 790 |
| 795 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)recognizer { | 791 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)recognizer { |
| 796 DCHECK([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]); | 792 DCHECK([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]); |
| 797 | 793 |
| 798 // If a drag is already in progress, do not allow another to start. | 794 // If a drag is already in progress, do not allow another to start. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 | 942 |
| 947 // Observer method. | 943 // Observer method. |
| 948 - (void)tabModel:(TabModel*)model | 944 - (void)tabModel:(TabModel*)model |
| 949 didMoveTab:(Tab*)tab | 945 didMoveTab:(Tab*)tab |
| 950 fromIndex:(NSUInteger)fromIndex | 946 fromIndex:(NSUInteger)fromIndex |
| 951 toIndex:(NSUInteger)toIndex { | 947 toIndex:(NSUInteger)toIndex { |
| 952 DCHECK(!_isReordering); | 948 DCHECK(!_isReordering); |
| 953 | 949 |
| 954 // Reorder the objects in _tabArray to keep in sync with the model ordering. | 950 // Reorder the objects in _tabArray to keep in sync with the model ordering. |
| 955 NSUInteger arrayIndex = [self indexForModelIndex:fromIndex]; | 951 NSUInteger arrayIndex = [self indexForModelIndex:fromIndex]; |
| 956 base::scoped_nsobject<TabView> view( | 952 TabView* view = [_tabArray objectAtIndex:arrayIndex]; |
| 957 [[_tabArray objectAtIndex:arrayIndex] retain]); | |
| 958 [_tabArray removeObject:view]; | 953 [_tabArray removeObject:view]; |
| 959 [_tabArray insertObject:view atIndex:toIndex]; | 954 [_tabArray insertObject:view atIndex:toIndex]; |
| 960 [self setNeedsLayoutWithAnimation]; | 955 [self setNeedsLayoutWithAnimation]; |
| 961 } | 956 } |
| 962 | 957 |
| 963 // Observer method. | 958 // Observer method. |
| 964 - (void)tabModel:(TabModel*)model | 959 - (void)tabModel:(TabModel*)model |
| 965 didChangeActiveTab:(Tab*)newTab | 960 didChangeActiveTab:(Tab*)newTab |
| 966 previousTab:(Tab*)previousTab | 961 previousTab:(Tab*)previousTab |
| 967 atIndex:(NSUInteger)modelIndex { | 962 atIndex:(NSUInteger)modelIndex { |
| 968 for (TabView* view in _tabArray.get()) { | 963 for (TabView* view in _tabArray) { |
| 969 [view setSelected:NO]; | 964 [view setSelected:NO]; |
| 970 } | 965 } |
| 971 | 966 |
| 972 NSUInteger index = [self indexForModelIndex:modelIndex]; | 967 NSUInteger index = [self indexForModelIndex:modelIndex]; |
| 973 TabView* activeView = [_tabArray objectAtIndex:index]; | 968 TabView* activeView = [_tabArray objectAtIndex:index]; |
| 974 [activeView setSelected:YES]; | 969 [activeView setSelected:YES]; |
| 975 | 970 |
| 976 // No need to animate this change, as selecting a new tab simply changes the | 971 // No need to animate this change, as selecting a new tab simply changes the |
| 977 // z-ordering of the TabViews. If a new tab was selected as a result of a tab | 972 // z-ordering of the TabViews. If a new tab was selected as a result of a tab |
| 978 // closure, then the animated layout has already been scheduled. | 973 // closure, then the animated layout has already been scheduled. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 [UIImage imageNamed:@"tabswitcher_tab_switcher_button"]; | 1020 [UIImage imageNamed:@"tabswitcher_tab_switcher_button"]; |
| 1026 tabSwitcherButtonIcon = [tabSwitcherButtonIcon | 1021 tabSwitcherButtonIcon = [tabSwitcherButtonIcon |
| 1027 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | 1022 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
| 1028 int tabSwitcherButtonIdsAccessibilityLabel = | 1023 int tabSwitcherButtonIdsAccessibilityLabel = |
| 1029 IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER; | 1024 IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER; |
| 1030 NSString* tabSwitcherButtonEnglishUiAutomationName = @"Enter Tab Switcher"; | 1025 NSString* tabSwitcherButtonEnglishUiAutomationName = @"Enter Tab Switcher"; |
| 1031 const CGFloat tabStripHeight = _view.frame.size.height; | 1026 const CGFloat tabStripHeight = _view.frame.size.height; |
| 1032 CGRect buttonFrame = | 1027 CGRect buttonFrame = |
| 1033 CGRectMake(CGRectGetMaxX(_view.frame) - kTabSwitcherButtonWidth, 0.0, | 1028 CGRectMake(CGRectGetMaxX(_view.frame) - kTabSwitcherButtonWidth, 0.0, |
| 1034 kTabSwitcherButtonWidth, tabStripHeight); | 1029 kTabSwitcherButtonWidth, tabStripHeight); |
| 1035 _tabSwitcherButton.reset( | 1030 _tabSwitcherButton = [UIButton buttonWithType:UIButtonTypeCustom]; |
| 1036 [[UIButton buttonWithType:UIButtonTypeCustom] retain]); | |
| 1037 [_tabSwitcherButton setTintColor:[UIColor whiteColor]]; | 1031 [_tabSwitcherButton setTintColor:[UIColor whiteColor]]; |
| 1038 [_tabSwitcherButton setFrame:buttonFrame]; | 1032 [_tabSwitcherButton setFrame:buttonFrame]; |
| 1039 [_tabSwitcherButton setContentMode:UIViewContentModeCenter]; | 1033 [_tabSwitcherButton setContentMode:UIViewContentModeCenter]; |
| 1040 [_tabSwitcherButton setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; | 1034 [_tabSwitcherButton setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; |
| 1041 [_tabSwitcherButton setBackgroundColor:[UIColor clearColor]]; | 1035 [_tabSwitcherButton setBackgroundColor:[UIColor clearColor]]; |
| 1042 [_tabSwitcherButton setExclusiveTouch:YES]; | 1036 [_tabSwitcherButton setExclusiveTouch:YES]; |
| 1043 [_tabSwitcherButton setImage:tabSwitcherButtonIcon | 1037 [_tabSwitcherButton setImage:tabSwitcherButtonIcon |
| 1044 forState:UIControlStateNormal]; | 1038 forState:UIControlStateNormal]; |
| 1045 // Set target/action to bubble up with command id as tag. | 1039 // Set target/action to bubble up with command id as tag. |
| 1046 [_tabSwitcherButton addTarget:nil | 1040 [_tabSwitcherButton addTarget:nil |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 } | 1161 } |
| 1168 | 1162 |
| 1169 // To handle content offset change without making views appear to jump, | 1163 // To handle content offset change without making views appear to jump, |
| 1170 // shift all of the subviews by an amount equal to the size change. | 1164 // shift all of the subviews by an amount equal to the size change. |
| 1171 [self shiftTabStripSubviews:oldOffset]; | 1165 [self shiftTabStripSubviews:oldOffset]; |
| 1172 return; | 1166 return; |
| 1173 } | 1167 } |
| 1174 | 1168 |
| 1175 NSUInteger numNonClosingTabsToLeft = 0; | 1169 NSUInteger numNonClosingTabsToLeft = 0; |
| 1176 NSUInteger i = 0; | 1170 NSUInteger i = 0; |
| 1177 for (TabView* tab in _tabArray.get()) { | 1171 for (TabView* tab in _tabArray) { |
| 1178 if ([_closingTabs containsObject:tab]) | 1172 if ([_closingTabs containsObject:tab]) |
| 1179 ++i; | 1173 ++i; |
| 1180 | 1174 |
| 1181 if (i == tabIndex) | 1175 if (i == tabIndex) |
| 1182 break; | 1176 break; |
| 1183 | 1177 |
| 1184 ++numNonClosingTabsToLeft; | 1178 ++numNonClosingTabsToLeft; |
| 1185 ++i; | 1179 ++i; |
| 1186 } | 1180 } |
| 1187 | 1181 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 | 1218 |
| 1225 - (void)updateScrollViewFrameForTabSwitcherButton { | 1219 - (void)updateScrollViewFrameForTabSwitcherButton { |
| 1226 CGRect tabFrame = _tabStripView.frame; | 1220 CGRect tabFrame = _tabStripView.frame; |
| 1227 tabFrame.size.width = _view.bounds.size.width; | 1221 tabFrame.size.width = _view.bounds.size.width; |
| 1228 if (!IsCompactTablet()) { | 1222 if (!IsCompactTablet()) { |
| 1229 tabFrame.size.width -= kTabSwitcherButtonWidth; | 1223 tabFrame.size.width -= kTabSwitcherButtonWidth; |
| 1230 _tabStripView.contentInset = UIEdgeInsetsZero; | 1224 _tabStripView.contentInset = UIEdgeInsetsZero; |
| 1231 [_tabSwitcherButtonBackgroundView setHidden:YES]; | 1225 [_tabSwitcherButtonBackgroundView setHidden:YES]; |
| 1232 } else { | 1226 } else { |
| 1233 if (!_tabSwitcherButtonBackgroundView) { | 1227 if (!_tabSwitcherButtonBackgroundView) { |
| 1234 _tabSwitcherButtonBackgroundView.reset([[UIImageView alloc] init]); | 1228 _tabSwitcherButtonBackgroundView = [[UIImageView alloc] init]; |
| 1235 const CGFloat tabStripHeight = _view.frame.size.height; | 1229 const CGFloat tabStripHeight = _view.frame.size.height; |
| 1236 const CGRect backgroundViewFrame = CGRectMake( | 1230 const CGRect backgroundViewFrame = CGRectMake( |
| 1237 CGRectGetMaxX(_view.frame) - kTabSwitcherButtonBackgroundWidth, 0.0, | 1231 CGRectGetMaxX(_view.frame) - kTabSwitcherButtonBackgroundWidth, 0.0, |
| 1238 kTabSwitcherButtonBackgroundWidth, tabStripHeight); | 1232 kTabSwitcherButtonBackgroundWidth, tabStripHeight); |
| 1239 [_tabSwitcherButtonBackgroundView setFrame:backgroundViewFrame]; | 1233 [_tabSwitcherButtonBackgroundView setFrame:backgroundViewFrame]; |
| 1240 [_tabSwitcherButtonBackgroundView | 1234 [_tabSwitcherButtonBackgroundView |
| 1241 setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; | 1235 setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; |
| 1242 UIImage* backgroundTabSwitcherImage = | 1236 UIImage* backgroundTabSwitcherImage = |
| 1243 [UIImage imageNamed:@"tabstrip_toggle_button_gradient"]; | 1237 [UIImage imageNamed:@"tabstrip_toggle_button_gradient"]; |
| 1244 [_tabSwitcherButtonBackgroundView setImage:backgroundTabSwitcherImage]; | 1238 [_tabSwitcherButtonBackgroundView setImage:backgroundTabSwitcherImage]; |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 } | 1542 } |
| 1549 | 1543 |
| 1550 @end | 1544 @end |
| 1551 | 1545 |
| 1552 #pragma mark - TabSwitcherAnimation | 1546 #pragma mark - TabSwitcherAnimation |
| 1553 | 1547 |
| 1554 @implementation TabStripController (TabSwitcherAnimation) | 1548 @implementation TabStripController (TabSwitcherAnimation) |
| 1555 | 1549 |
| 1556 - (TabSwitcherTabStripPlaceholderView*)placeholderView { | 1550 - (TabSwitcherTabStripPlaceholderView*)placeholderView { |
| 1557 TabSwitcherTabStripPlaceholderView* placeholderView = | 1551 TabSwitcherTabStripPlaceholderView* placeholderView = |
| 1558 [[[TabSwitcherTabStripPlaceholderView alloc] | 1552 [[TabSwitcherTabStripPlaceholderView alloc] |
| 1559 initWithFrame:self.view.bounds] autorelease]; | 1553 initWithFrame:self.view.bounds]; |
| 1560 CGFloat xOffset = [_tabStripView contentOffset].x; | 1554 CGFloat xOffset = [_tabStripView contentOffset].x; |
| 1561 UIView* previousView = nil; | 1555 UIView* previousView = nil; |
| 1562 const NSUInteger selectedModelIndex = | 1556 const NSUInteger selectedModelIndex = |
| 1563 [_tabModel indexOfTab:[_tabModel currentTab]]; | 1557 [_tabModel indexOfTab:[_tabModel currentTab]]; |
| 1564 const NSUInteger selectedArrayIndex = | 1558 const NSUInteger selectedArrayIndex = |
| 1565 [self indexForModelIndex:selectedModelIndex]; | 1559 [self indexForModelIndex:selectedModelIndex]; |
| 1566 [self updateContentSizeAndRepositionViews]; | 1560 [self updateContentSizeAndRepositionViews]; |
| 1567 [self layoutTabStripSubviews]; | 1561 [self layoutTabStripSubviews]; |
| 1568 for (NSUInteger tabArrayIndex = 0; tabArrayIndex < [_tabArray count]; | 1562 for (NSUInteger tabArrayIndex = 0; tabArrayIndex < [_tabArray count]; |
| 1569 ++tabArrayIndex) { | 1563 ++tabArrayIndex) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1592 | 1586 |
| 1593 @implementation TabStripController (Testing) | 1587 @implementation TabStripController (Testing) |
| 1594 | 1588 |
| 1595 - (TabView*)existingTabViewForTab:(Tab*)tab { | 1589 - (TabView*)existingTabViewForTab:(Tab*)tab { |
| 1596 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; | 1590 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; |
| 1597 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; | 1591 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; |
| 1598 return [_tabArray objectAtIndex:tabViewIndex]; | 1592 return [_tabArray objectAtIndex:tabViewIndex]; |
| 1599 } | 1593 } |
| 1600 | 1594 |
| 1601 @end | 1595 @end |
| OLD | NEW |