| 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 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 // current position. (If dropped, the tab would be at this index in the model.) | 279 // current position. (If dropped, the tab would be at this index in the model.) |
| 280 // TODO(rohitrao): Implement this method. | 280 // TODO(rohitrao): Implement this method. |
| 281 - (NSUInteger)modelIndexForDraggedTab; | 281 - (NSUInteger)modelIndexForDraggedTab; |
| 282 #endif | 282 #endif |
| 283 | 283 |
| 284 // Returns the horizontal visible tab strip width used to compute the tab width | 284 // Returns the horizontal visible tab strip width used to compute the tab width |
| 285 // and the tabs and new tab button in regular layout mode. | 285 // and the tabs and new tab button in regular layout mode. |
| 286 // Takes into account whether or not the mode toggle button is showing. | 286 // Takes into account whether or not the mode toggle button is showing. |
| 287 - (CGFloat)tabStripVisibleSpace; | 287 - (CGFloat)tabStripVisibleSpace; |
| 288 | 288 |
| 289 // Shift all of the tab strip subviews by an amount equal to the content offset |
| 290 // change, which effectively places the subviews back where they were before the |
| 291 // change, in terms of screen coordinates. |
| 292 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset; |
| 293 |
| 289 // Updates the scroll view's content size based on the current set of tabs and | 294 // Updates the scroll view's content size based on the current set of tabs and |
| 290 // closing tabs. After updating the content size, repositions views so they | 295 // closing tabs. After updating the content size, repositions views so they |
| 291 // they will appear stationary on screen. | 296 // they will appear stationary on screen. |
| 292 - (void)updateContentSizeAndRepositionViews; | 297 - (void)updateContentSizeAndRepositionViews; |
| 293 | 298 |
| 294 // Returns the frame, in the scroll view content's coordinate system, of the | 299 // Returns the frame, in the scroll view content's coordinate system, of the |
| 295 // given tab view. | 300 // given tab view. |
| 296 - (CGRect)scrollViewFrameForTab:(TabView*)view; | 301 - (CGRect)scrollViewFrameForTab:(TabView*)view; |
| 297 | 302 |
| 298 // Returns the portion of |frame| which is not covered by |frameOnTop|. | 303 // Returns the portion of |frame| which is not covered by |frameOnTop|. |
| 299 - (CGRect)calculateVisibleFrameForFrame:(CGRect)frame | 304 - (CGRect)calculateVisibleFrameForFrame:(CGRect)frame |
| 300 whenUnderFrame:(CGRect)frameOnTop; | 305 whenUnderFrame:(CGRect)frameOnTop; |
| 301 | 306 |
| 302 // Schedules a layout of the scroll view and sets the internal |_animateLayout| | 307 // Schedules a layout of the scroll view and sets the internal |_animateLayout| |
| 303 // flag so that the layout will be animated. | 308 // flag so that the layout will be animated. |
| 304 - (void)setNeedsLayoutWithAnimation; | 309 - (void)setNeedsLayoutWithAnimation; |
| 305 | 310 |
| 306 // Returns the maximum number of collapsed tabs depending on the current layout | 311 // Returns the maximum number of collapsed tabs depending on the current layout |
| 307 // mode. | 312 // mode. |
| 308 - (NSUInteger)maxNumCollapsedTabs; | 313 - (NSUInteger)maxNumCollapsedTabs; |
| 309 | 314 |
| 310 // Returns the tab overlap width depending on the current layout mode. | 315 // Returns the tab overlap width depending on the current layout mode. |
| 311 - (CGFloat)tabOverlap; | 316 - (CGFloat)tabOverlap; |
| 312 | 317 |
| 313 // Returns the minimum tab view width depending on the current layout mode. | 318 // Returns the minimum tab view width depending on the current layout mode. |
| 314 - (CGFloat)minTabWidth; | 319 - (CGFloat)minTabWidth; |
| 315 | 320 |
| 321 // Automatically scroll the tab strip view to keep the newly inserted tab view |
| 322 // visible. |
| 323 // This method must be called with a valid |tabIndex|. |
| 324 - (void)autoScrollForNewTab:(NSUInteger)tabIndex; |
| 325 |
| 316 // Updates the content offset of the tab strip view in order to keep the | 326 // Updates the content offset of the tab strip view in order to keep the |
| 317 // selected tab view visible. | 327 // selected tab view visible. |
| 318 // Content offset adjustement is only needed/performed in compact mode or | 328 // Content offset adjustement is only needed/performed in compact mode or |
| 319 // regular mode for newly opened tabs. | 329 // regular mode for newly opened tabs. |
| 320 // This method must be called with a valid |tabIndex|. | 330 // This method must be called with a valid |tabIndex|. |
| 321 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex | 331 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex |
| 322 isNewTab:(BOOL)isNewTab; | 332 isNewTab:(BOOL)isNewTab; |
| 323 | 333 |
| 324 // Update the frame of the tab strip view (scrollview) frame, content inset and | 334 // Update the frame of the tab strip view (scrollview) frame, content inset and |
| 325 // toggle buttons states depending on the current layout mode. | 335 // toggle buttons states depending on the current layout mode. |
| (...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 | 1172 |
| 1163 - (void)removeTabSwitcherToggleButton { | 1173 - (void)removeTabSwitcherToggleButton { |
| 1164 // Remove the button view. | 1174 // Remove the button view. |
| 1165 DCHECK(_tabSwitcherToggleButton); | 1175 DCHECK(_tabSwitcherToggleButton); |
| 1166 [_tabSwitcherToggleButton removeFromSuperview]; | 1176 [_tabSwitcherToggleButton removeFromSuperview]; |
| 1167 _tabSwitcherToggleButton = nil; | 1177 _tabSwitcherToggleButton = nil; |
| 1168 // Extend the scroll view. | 1178 // Extend the scroll view. |
| 1169 [self updateScrollViewFrameForToggleButton]; | 1179 [self updateScrollViewFrameForToggleButton]; |
| 1170 } | 1180 } |
| 1171 | 1181 |
| 1182 - (void)shiftTabStripSubviews:(CGPoint)oldContentOffset { |
| 1183 CGFloat dx = [_tabStripView contentOffset].x - oldContentOffset.x; |
| 1184 for (UIView* view in [_tabStripView subviews]) { |
| 1185 CGRect frame = [view frame]; |
| 1186 frame.origin.x += dx; |
| 1187 [view setFrame:frame]; |
| 1188 _targetFrames.AddFrame(view, frame); |
| 1189 } |
| 1190 } |
| 1191 |
| 1172 - (void)updateContentSizeAndRepositionViews { | 1192 - (void)updateContentSizeAndRepositionViews { |
| 1173 // TODO(rohitrao): The following lines are duplicated in | 1193 // TODO(rohitrao): The following lines are duplicated in |
| 1174 // layoutTabStripSubviews. Find a way to consolidate this logic. | 1194 // layoutTabStripSubviews. Find a way to consolidate this logic. |
| 1175 const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; | 1195 const NSUInteger tabCount = [_tabArray count] - [_closingTabs count]; |
| 1176 if (!tabCount) | 1196 if (!tabCount) |
| 1177 return; | 1197 return; |
| 1178 const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); | 1198 const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); |
| 1179 CGFloat visibleSpace = [self tabStripVisibleSpace]; | 1199 CGFloat visibleSpace = [self tabStripVisibleSpace]; |
| 1180 _currentTabWidth = | 1200 _currentTabWidth = |
| 1181 (visibleSpace + ([self tabOverlap] * (tabCount - 1))) / tabCount; | 1201 (visibleSpace + ([self tabOverlap] * (tabCount - 1))) / tabCount; |
| 1182 _currentTabWidth = MIN(_currentTabWidth, kMaxTabWidth); | 1202 _currentTabWidth = MIN(_currentTabWidth, kMaxTabWidth); |
| 1183 _currentTabWidth = MAX(_currentTabWidth, [self minTabWidth]); | 1203 _currentTabWidth = MAX(_currentTabWidth, [self minTabWidth]); |
| 1184 | 1204 |
| 1185 // Set the content size to be large enough to contain all the tabs at the | 1205 // Set the content size to be large enough to contain all the tabs at the |
| 1186 // desired width, with the standard overlap, plus the new tab button. | 1206 // desired width, with the standard overlap, plus the new tab button. |
| 1187 CGSize contentSize = CGSizeMake( | 1207 CGSize contentSize = CGSizeMake( |
| 1188 _currentTabWidth * tabCount - ([self tabOverlap] * (tabCount - 1)) + | 1208 _currentTabWidth * tabCount - ([self tabOverlap] * (tabCount - 1)) + |
| 1189 CGRectGetWidth([_buttonNewTab frame]) - kNewTabOverlap, | 1209 CGRectGetWidth([_buttonNewTab frame]) - kNewTabOverlap, |
| 1190 tabHeight); | 1210 tabHeight); |
| 1191 if (CGSizeEqualToSize([_tabStripView contentSize], contentSize)) | 1211 if (CGSizeEqualToSize([_tabStripView contentSize], contentSize)) |
| 1192 return; | 1212 return; |
| 1193 | 1213 |
| 1194 // Background: The scroll view might change the content offset when updating | 1214 // Background: The scroll view might change the content offset when updating |
| 1195 // the content size. This can happen when the old content offset would result | 1215 // the content size. This can happen when the old content offset would result |
| 1196 // in an overscroll at the new content size. (Note that the content offset | 1216 // in an overscroll at the new content size. (Note that the content offset |
| 1197 // will never change if the content size is growing.) | 1217 // will never change if the content size is growing.) |
| 1198 // | 1218 // |
| 1199 // To handle this without making views appear to jump, shift all of the | 1219 // To handle this without making views appear to jump, shift all of the |
| 1200 // subviews by an amount equal to the size change. This effectively places | 1220 // subviews by an amount equal to the size change. |
| 1201 // the subviews back where they were before the change, in terms of screen | |
| 1202 // coordinates. | |
| 1203 CGPoint oldOffset = [_tabStripView contentOffset]; | 1221 CGPoint oldOffset = [_tabStripView contentOffset]; |
| 1204 [_tabStripView setContentSize:contentSize]; | 1222 [_tabStripView setContentSize:contentSize]; |
| 1205 | 1223 [self shiftTabStripSubviews:oldOffset]; |
| 1206 CGFloat dx = [_tabStripView contentOffset].x - oldOffset.x; | |
| 1207 for (UIView* view in [_tabStripView subviews]) { | |
| 1208 CGRect frame = [view frame]; | |
| 1209 frame.origin.x += dx; | |
| 1210 [view setFrame:frame]; | |
| 1211 _targetFrames.AddFrame(view, frame); | |
| 1212 } | |
| 1213 } | 1224 } |
| 1214 | 1225 |
| 1215 - (CGRect)scrollViewFrameForTab:(TabView*)view { | 1226 - (CGRect)scrollViewFrameForTab:(TabView*)view { |
| 1216 NSUInteger index = [self modelIndexForTabView:view]; | 1227 NSUInteger index = [self modelIndexForTabView:view]; |
| 1217 | 1228 |
| 1218 CGRect frame = [view frame]; | 1229 CGRect frame = [view frame]; |
| 1219 frame.origin.x = | 1230 frame.origin.x = |
| 1220 (_currentTabWidth * index) - ([self tabOverlap] * (index - 1)); | 1231 (_currentTabWidth * index) - ([self tabOverlap] * (index - 1)); |
| 1221 return frame; | 1232 return frame; |
| 1222 } | 1233 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1245 } | 1256 } |
| 1246 | 1257 |
| 1247 - (CGFloat)tabOverlap { | 1258 - (CGFloat)tabOverlap { |
| 1248 return IsCompactTablet() ? kTabOverlapForCompactLayout : kTabOverlap; | 1259 return IsCompactTablet() ? kTabOverlapForCompactLayout : kTabOverlap; |
| 1249 } | 1260 } |
| 1250 | 1261 |
| 1251 - (CGFloat)minTabWidth { | 1262 - (CGFloat)minTabWidth { |
| 1252 return IsCompactTablet() ? kMinTabWidthForCompactLayout : kMinTabWidth; | 1263 return IsCompactTablet() ? kMinTabWidthForCompactLayout : kMinTabWidth; |
| 1253 } | 1264 } |
| 1254 | 1265 |
| 1266 - (void)autoScrollForNewTab:(NSUInteger)tabIndex { |
| 1267 DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); |
| 1268 |
| 1269 // The following code calculates the amount of scroll needed to make |
| 1270 // |tabIndex| visible in the "virtual" coordinate system, where root is x=0 |
| 1271 // and it contains all the tabs laid out as if the tabstrip was infinitely |
| 1272 // long. The amount of scroll is calculated as a desired length that it is |
| 1273 // just large enough to contain all the tabs to the left of |tabIndex|, with |
| 1274 // the standard overlap. |
| 1275 if (tabIndex == [_tabArray count] - 1) { |
| 1276 const CGFloat tabStripAvailableSpace = |
| 1277 _tabStripView.frame.size.width - _tabStripView.contentInset.right; |
| 1278 CGPoint oldOffset = [_tabStripView contentOffset]; |
| 1279 if (_tabStripView.contentSize.width > tabStripAvailableSpace) { |
| 1280 CGFloat scrollToPoint = |
| 1281 _tabStripView.contentSize.width - tabStripAvailableSpace; |
| 1282 [_tabStripView setContentOffset:CGPointMake(scrollToPoint, 0)]; |
| 1283 } |
| 1284 |
| 1285 // To handle content offset change without making views appear to jump, |
| 1286 // shift all of the subviews by an amount equal to the size change. |
| 1287 [self shiftTabStripSubviews:oldOffset]; |
| 1288 return; |
| 1289 } |
| 1290 |
| 1291 NSUInteger numNonClosingTabsToLeft = 0; |
| 1292 NSUInteger i = 0; |
| 1293 for (TabView* tab in _tabArray.get()) { |
| 1294 if ([_closingTabs containsObject:tab]) |
| 1295 ++i; |
| 1296 |
| 1297 if (i == tabIndex) |
| 1298 break; |
| 1299 |
| 1300 ++numNonClosingTabsToLeft; |
| 1301 ++i; |
| 1302 } |
| 1303 |
| 1304 const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); |
| 1305 CGRect scrollRect = |
| 1306 CGRectMake(_currentTabWidth * numNonClosingTabsToLeft - |
| 1307 ([self tabOverlap] * (numNonClosingTabsToLeft - 1)), |
| 1308 0, _currentTabWidth, tabHeight); |
| 1309 [_tabStripView scrollRectToVisible:scrollRect animated:YES]; |
| 1310 } |
| 1311 |
| 1255 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex | 1312 - (void)updateContentOffsetForTabIndex:(NSUInteger)tabIndex |
| 1256 isNewTab:(BOOL)isNewTab { | 1313 isNewTab:(BOOL)isNewTab { |
| 1257 DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); | 1314 DCHECK_NE(NSNotFound, static_cast<NSInteger>(tabIndex)); |
| 1258 | 1315 |
| 1259 if (experimental_flags::IsTabStripAutoScrollNewTabsEnabled() && isNewTab) { | 1316 if (experimental_flags::IsTabStripAutoScrollNewTabsEnabled() && isNewTab) { |
| 1260 // The following code calculates the amount of scroll needed to make | 1317 [self autoScrollForNewTab:tabIndex]; |
| 1261 // |tabIndex| visible in the "virtual" coordinate system, where root is x=0 | |
| 1262 // and it contains all the tabs laid out as if the tabstrip was infinitely | |
| 1263 // long. The amount of scroll is calculated as a desired length that it is | |
| 1264 // just large enough to contain all the tabs to the left of |tabIndex|, with | |
| 1265 // the standard overlap. | |
| 1266 NSUInteger numNonClosingTabsToLeft = 0; | |
| 1267 NSUInteger i = 0; | |
| 1268 for (TabView* tab in _tabArray.get()) { | |
| 1269 if ([_closingTabs containsObject:tab]) | |
| 1270 ++i; | |
| 1271 | |
| 1272 if (i == tabIndex) | |
| 1273 break; | |
| 1274 | |
| 1275 ++numNonClosingTabsToLeft; | |
| 1276 ++i; | |
| 1277 } | |
| 1278 | |
| 1279 const CGFloat tabHeight = CGRectGetHeight([_tabStripView bounds]); | |
| 1280 CGRect scrollRect = | |
| 1281 CGRectMake(_currentTabWidth * numNonClosingTabsToLeft - | |
| 1282 ([self tabOverlap] * (numNonClosingTabsToLeft - 1)), | |
| 1283 0, _currentTabWidth, tabHeight); | |
| 1284 [_tabStripView scrollRectToVisible:scrollRect animated:YES]; | |
| 1285 return; | 1318 return; |
| 1286 } | 1319 } |
| 1287 | 1320 |
| 1288 if (IsCompactTablet()) { | 1321 if (IsCompactTablet()) { |
| 1289 if (tabIndex == [_tabArray count] - 1) { | 1322 if (tabIndex == [_tabArray count] - 1) { |
| 1290 const CGFloat tabStripAvailableSpace = | 1323 const CGFloat tabStripAvailableSpace = |
| 1291 _tabStripView.frame.size.width - _tabStripView.contentInset.right; | 1324 _tabStripView.frame.size.width - _tabStripView.contentInset.right; |
| 1292 if (_tabStripView.contentSize.width > tabStripAvailableSpace) { | 1325 if (_tabStripView.contentSize.width > tabStripAvailableSpace) { |
| 1293 CGFloat scrollToPoint = | 1326 CGFloat scrollToPoint = |
| 1294 _tabStripView.contentSize.width - tabStripAvailableSpace; | 1327 _tabStripView.contentSize.width - tabStripAvailableSpace; |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 | 1722 |
| 1690 @implementation TabStripController (Testing) | 1723 @implementation TabStripController (Testing) |
| 1691 | 1724 |
| 1692 - (TabView*)existingTabViewForTab:(Tab*)tab { | 1725 - (TabView*)existingTabViewForTab:(Tab*)tab { |
| 1693 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; | 1726 NSUInteger tabIndex = [_tabModel indexOfTab:tab]; |
| 1694 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; | 1727 NSUInteger tabViewIndex = [self indexForModelIndex:tabIndex]; |
| 1695 return [_tabArray objectAtIndex:tabViewIndex]; | 1728 return [_tabArray objectAtIndex:tabViewIndex]; |
| 1696 } | 1729 } |
| 1697 | 1730 |
| 1698 @end | 1731 @end |
| OLD | NEW |