| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/history/tab_history_view_controller.h" | 5 #import "ios/chrome/browser/ui/history/tab_history_view_controller.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/mac/foundation_util.h" | 8 #include "base/mac/foundation_util.h" |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" | 10 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" |
| 11 #include "ios/chrome/browser/ui/commands/ios_command_ids.h" | 11 #include "ios/chrome/browser/ui/commands/ios_command_ids.h" |
| 12 #import "ios/chrome/browser/ui/history/tab_history_cell.h" | 12 #import "ios/chrome/browser/ui/history/tab_history_cell.h" |
| 13 #include "ios/chrome/browser/ui/rtl_geometry.h" | 13 #include "ios/chrome/browser/ui/rtl_geometry.h" |
| 14 #import "ios/third_party/material_components_ios/src/components/Ink/src/Material
Ink.h" | 14 #import "ios/third_party/material_components_ios/src/components/Ink/src/Material
Ink.h" |
| 15 #import "ios/web/navigation/crw_session_entry.h" | |
| 16 #include "ios/web/public/favicon_status.h" | 15 #include "ios/web/public/favicon_status.h" |
| 17 #include "ios/web/public/navigation_item.h" | 16 #include "ios/web/public/navigation_item.h" |
| 18 #include "ui/gfx/image/image.h" | 17 #include "ui/gfx/image/image.h" |
| 19 | 18 |
| 20 #if !defined(__has_feature) || !__has_feature(objc_arc) | 19 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 21 #error "This file requires ARC support." | 20 #error "This file requires ARC support." |
| 22 #endif | 21 #endif |
| 23 | 22 |
| 24 namespace { | 23 namespace { |
| 25 | 24 |
| 26 // Visible percentage of the last visible row on the Tools menu if the | 25 // Visible percentage of the last visible row on the Tools menu if the |
| 27 // Tools menu is scrollable. | 26 // Tools menu is scrollable. |
| 28 const CGFloat kLastRowVisiblePercentage = 0.6; | 27 const CGFloat kLastRowVisiblePercentage = 0.6; |
| 29 // Reuse identifier for cells. | 28 // Reuse identifier for cells. |
| 30 NSString* cellIdentifier = @"TabHistoryCell"; | 29 NSString* const kCellIdentifier = @"TabHistoryCell"; |
| 31 NSString* footerIdentifier = @"Footer"; | 30 NSString* const kFooterIdentifier = @"Footer"; |
| 32 NSString* headerIdentifier = @"Header"; | 31 NSString* const kHeaderIdentifier = @"Header"; |
| 32 // The collection view's a11y label. |
| 33 NSString* const kCollectionViewLabel = @"Tab History"; |
| 33 // Height of rows. | 34 // Height of rows. |
| 34 const CGFloat kCellHeight = 48.0; | 35 const CGFloat kCellHeight = 48.0; |
| 35 // Fraction height for partially visible row. | 36 // Fraction height for partially visible row. |
| 36 const CGFloat kCellHeightLastRow = kCellHeight * kLastRowVisiblePercentage; | 37 const CGFloat kCellHeightLastRow = kCellHeight * kLastRowVisiblePercentage; |
| 37 // Width and leading for the header view. | 38 // Width and leading for the header view. |
| 38 const CGFloat kHeaderLeadingInset = 0; | 39 const CGFloat kHeaderLeadingInset = 0; |
| 39 const CGFloat kHeaderWidth = 48; | 40 const CGFloat kHeaderWidth = 48; |
| 40 // Leading and trailing insets for cell items. | 41 // Leading and trailing insets for cell items. |
| 41 const CGFloat kCellLeadingInset = kHeaderLeadingInset + kHeaderWidth; | 42 const CGFloat kCellLeadingInset = kHeaderLeadingInset + kHeaderWidth; |
| 42 const CGFloat kCellTrailingInset = 16; | 43 const CGFloat kCellTrailingInset = 16; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 64 DCHECK(offsets.at([path section]).size()); | 65 DCHECK(offsets.at([path section]).size()); |
| 65 | 66 |
| 66 return offsets.at([path section]).at(0); | 67 return offsets.at([path section]).at(0); |
| 67 } | 68 } |
| 68 | 69 |
| 69 // Height for the footer view. | 70 // Height for the footer view. |
| 70 NS_INLINE CGFloat FooterHeight() { | 71 NS_INLINE CGFloat FooterHeight() { |
| 71 return 1.0 / [[UIScreen mainScreen] scale]; | 72 return 1.0 / [[UIScreen mainScreen] scale]; |
| 72 } | 73 } |
| 73 | 74 |
| 75 // Returns a vector of of NavigationItemLists where the NavigationItems in |
| 76 // |items| are separated by host. |
| 77 NS_INLINE std::vector<web::NavigationItemList> PartitionItemsByHost( |
| 78 const web::NavigationItemList& items) { |
| 79 std::vector<web::NavigationItemList> partitionedItems; |
| 80 // Used to store the previous host when partitioning NavigationItems. |
| 81 std::string previousHost; |
| 82 // The NavigationItemList containing NavigationItems with the same host. |
| 83 web::NavigationItemList itemsWithSameHostname; |
| 84 // Separate the items in |items| by host. |
| 85 for (web::NavigationItem* item : items) { |
| 86 std::string currentHost = item->GetURL().host(); |
| 87 if (previousHost.empty()) |
| 88 previousHost = currentHost; |
| 89 // TODO: This should use some sort of Top Level Domain matching instead of |
| 90 // explicit host match so that images.googe.com matches shopping.google.com. |
| 91 if (previousHost == currentHost) { |
| 92 itemsWithSameHostname.push_back(item); |
| 93 } else { |
| 94 partitionedItems.push_back(itemsWithSameHostname); |
| 95 itemsWithSameHostname = web::NavigationItemList(1, item); |
| 96 previousHost = currentHost; |
| 97 } |
| 98 } |
| 99 // Add the last list contiaining the same host. |
| 100 if (!itemsWithSameHostname.empty()) |
| 101 partitionedItems.push_back(itemsWithSameHostname); |
| 102 return partitionedItems; |
| 103 } |
| 104 |
| 74 } // namespace | 105 } // namespace |
| 75 | 106 |
| 76 @interface TabHistoryViewControllerLayout : UICollectionViewLayout | 107 @interface TabHistoryViewControllerLayout : UICollectionViewLayout |
| 77 @end | 108 @end |
| 78 | 109 |
| 79 @implementation TabHistoryViewControllerLayout { | 110 @implementation TabHistoryViewControllerLayout { |
| 80 ItemOffsetVector _itemYOffsets; | 111 ItemOffsetVector _itemYOffsets; |
| 81 CGFloat _containerCalculatedHeight; | 112 CGFloat _containerCalculatedHeight; |
| 82 CGFloat _containerWidth; | 113 CGFloat _containerWidth; |
| 83 CGFloat _cellItemWidth; | 114 CGFloat _cellItemWidth; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 [attributes setZIndex:0]; | 243 [attributes setZIndex:0]; |
| 213 } | 244 } |
| 214 | 245 |
| 215 return attributes; | 246 return attributes; |
| 216 } | 247 } |
| 217 | 248 |
| 218 @end | 249 @end |
| 219 | 250 |
| 220 @interface TabHistoryViewController ()<MDCInkTouchControllerDelegate> { | 251 @interface TabHistoryViewController ()<MDCInkTouchControllerDelegate> { |
| 221 MDCInkTouchController* _inkTouchController; | 252 MDCInkTouchController* _inkTouchController; |
| 222 NSArray* _partitionedEntries; | 253 // A vector of NavigationItemLists where the NavigationItems are separated |
| 223 NSArray* _sessionEntries; | 254 // by hostname. |
| 255 std::vector<web::NavigationItemList> _partitionedItems; |
| 224 } | 256 } |
| 257 |
| 258 // Returns the NavigationItem corresponding with |indexPath|. |
| 259 - (const web::NavigationItem*)itemAtIndexPath:(NSIndexPath*)indexPath; |
| 260 |
| 261 // Removes all NavigationItem pointers from this class. Tapping a cell that |
| 262 // triggers a navigation may delete NavigationItems, so NavigationItem |
| 263 // references should be reset to avoid use-after-free errors. |
| 264 - (void)clearNavigationItems; |
| 265 |
| 225 @end | 266 @end |
| 226 | 267 |
| 227 @implementation TabHistoryViewController | 268 @implementation TabHistoryViewController |
| 228 | 269 |
| 229 - (NSArray*)sessionEntries { | 270 - (instancetype)initWithItems:(const web::NavigationItemList&)items { |
| 230 return _sessionEntries; | 271 TabHistoryViewControllerLayout* layout = |
| 272 [[TabHistoryViewControllerLayout alloc] init]; |
| 273 if ((self = [super initWithCollectionViewLayout:layout])) { |
| 274 // Populate |_partitionedItems|. |
| 275 _partitionedItems = PartitionItemsByHost(items); |
| 276 |
| 277 // Set up the UICollectionView. |
| 278 UICollectionView* collectionView = [self collectionView]; |
| 279 collectionView.accessibilityLabel = kCollectionViewLabel; |
| 280 collectionView.backgroundColor = [UIColor whiteColor]; |
| 281 [collectionView registerClass:[TabHistoryCell class] |
| 282 forCellWithReuseIdentifier:kCellIdentifier]; |
| 283 [collectionView registerClass:[TabHistorySectionHeader class] |
| 284 forSupplementaryViewOfKind:UICollectionElementKindSectionHeader |
| 285 withReuseIdentifier:kHeaderIdentifier]; |
| 286 [collectionView registerClass:[TabHistorySectionFooter class] |
| 287 forSupplementaryViewOfKind:UICollectionElementKindSectionFooter |
| 288 withReuseIdentifier:kFooterIdentifier]; |
| 289 |
| 290 // Set up the ink controller. |
| 291 _inkTouchController = |
| 292 [[MDCInkTouchController alloc] initWithView:collectionView]; |
| 293 [_inkTouchController setDelegate:self]; |
| 294 [_inkTouchController addInkView]; |
| 295 } |
| 296 return self; |
| 231 } | 297 } |
| 232 | 298 |
| 233 #pragma mark Public Methods | 299 #pragma mark Public Methods |
| 234 | 300 |
| 235 - (CGFloat)optimalHeight:(CGFloat)suggestedHeight { | 301 - (CGFloat)optimalHeight:(CGFloat)suggestedHeight { |
| 236 DCHECK(suggestedHeight >= kCellHeight); | 302 DCHECK(suggestedHeight >= kCellHeight); |
| 237 CGFloat optimalHeight = 0; | 303 CGFloat optimalHeight = 0; |
| 238 | 304 |
| 239 for (NSArray* sectionArray in _partitionedEntries) { | 305 for (web::NavigationItemList& itemsWithSameHost : _partitionedItems) { |
| 240 NSUInteger sectionItemCount = [sectionArray count]; | 306 for (size_t count = 0; count < itemsWithSameHost.size(); ++count) { |
| 241 for (NSUInteger i = 0; i < sectionItemCount; ++i) { | |
| 242 CGFloat proposedHeight = optimalHeight + kCellHeight; | 307 CGFloat proposedHeight = optimalHeight + kCellHeight; |
| 243 | 308 |
| 244 if (proposedHeight > suggestedHeight) { | 309 if (proposedHeight > suggestedHeight) { |
| 245 CGFloat difference = proposedHeight - suggestedHeight; | 310 CGFloat difference = proposedHeight - suggestedHeight; |
| 246 if (difference > kCellHeightLastRow) { | 311 if (difference > kCellHeightLastRow) { |
| 247 return optimalHeight + kCellHeightLastRow; | 312 return optimalHeight + kCellHeightLastRow; |
| 248 } else { | 313 } else { |
| 249 return optimalHeight - kCellHeight + kCellHeightLastRow; | 314 return optimalHeight - kCellHeight + kCellHeightLastRow; |
| 250 } | 315 } |
| 251 } | 316 } |
| 252 | 317 |
| 253 optimalHeight = proposedHeight; | 318 optimalHeight = proposedHeight; |
| 254 } | 319 } |
| 255 | 320 |
| 256 optimalHeight += FooterHeight(); | 321 optimalHeight += FooterHeight(); |
| 257 } | 322 } |
| 258 | 323 |
| 259 // If this point is reached, it means the entire content fits and this last | 324 // If this point is reached, it means the entire content fits and this last |
| 260 // section should not include the footer. | 325 // section should not include the footer. |
| 261 optimalHeight -= FooterHeight(); | 326 optimalHeight -= FooterHeight(); |
| 262 | 327 |
| 263 return optimalHeight; | 328 return optimalHeight; |
| 264 } | 329 } |
| 265 | 330 |
| 266 - (instancetype)init { | |
| 267 TabHistoryViewControllerLayout* layout = | |
| 268 [[TabHistoryViewControllerLayout alloc] init]; | |
| 269 | |
| 270 return [self initWithCollectionViewLayout:layout]; | |
| 271 } | |
| 272 | |
| 273 - (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout*)layout { | |
| 274 self = [super initWithCollectionViewLayout:layout]; | |
| 275 if (self) { | |
| 276 UICollectionView* collectionView = [self collectionView]; | |
| 277 [collectionView setBackgroundColor:[UIColor whiteColor]]; | |
| 278 | |
| 279 [collectionView registerClass:[TabHistoryCell class] | |
| 280 forCellWithReuseIdentifier:cellIdentifier]; | |
| 281 | |
| 282 [collectionView registerClass:[TabHistorySectionHeader class] | |
| 283 forSupplementaryViewOfKind:UICollectionElementKindSectionHeader | |
| 284 withReuseIdentifier:headerIdentifier]; | |
| 285 | |
| 286 [collectionView registerClass:[TabHistorySectionFooter class] | |
| 287 forSupplementaryViewOfKind:UICollectionElementKindSectionFooter | |
| 288 withReuseIdentifier:footerIdentifier]; | |
| 289 | |
| 290 _inkTouchController = | |
| 291 [[MDCInkTouchController alloc] initWithView:collectionView]; | |
| 292 [_inkTouchController setDelegate:self]; | |
| 293 [_inkTouchController addInkView]; | |
| 294 } | |
| 295 | |
| 296 return self; | |
| 297 } | |
| 298 | |
| 299 #pragma mark UICollectionViewDelegate | 331 #pragma mark UICollectionViewDelegate |
| 300 | 332 |
| 301 - (void)collectionView:(UICollectionView*)collectionView | 333 - (void)collectionView:(UICollectionView*)collectionView |
| 302 didSelectItemAtIndexPath:(NSIndexPath*)indexPath { | 334 didSelectItemAtIndexPath:(NSIndexPath*)indexPath { |
| 303 UICollectionViewCell* cell = | 335 TabHistoryCell* cell = base::mac::ObjCCastStrict<TabHistoryCell>( |
| 304 [collectionView cellForItemAtIndexPath:indexPath]; | 336 [collectionView cellForItemAtIndexPath:indexPath]); |
| 305 [collectionView chromeExecuteCommand:cell]; | 337 [collectionView chromeExecuteCommand:cell]; |
| 338 [self clearNavigationItems]; |
| 306 } | 339 } |
| 307 | 340 |
| 308 #pragma mark UICollectionViewDataSource | 341 #pragma mark UICollectionViewDataSource |
| 309 | 342 |
| 310 - (CRWSessionEntry*)entryForIndexPath:(NSIndexPath*)indexPath { | |
| 311 NSInteger section = [indexPath section]; | |
| 312 NSInteger item = [indexPath item]; | |
| 313 | |
| 314 DCHECK(section < (NSInteger)[_partitionedEntries count]); | |
| 315 DCHECK(item < (NSInteger)[[_partitionedEntries objectAtIndex:section] count]); | |
| 316 NSArray* sectionedArray = [_partitionedEntries objectAtIndex:section]; | |
| 317 | |
| 318 return [sectionedArray objectAtIndex:item]; | |
| 319 } | |
| 320 | |
| 321 - (NSInteger)collectionView:(UICollectionView*)collectionView | 343 - (NSInteger)collectionView:(UICollectionView*)collectionView |
| 322 numberOfItemsInSection:(NSInteger)section { | 344 numberOfItemsInSection:(NSInteger)section { |
| 323 DCHECK(section < (NSInteger)[_partitionedEntries count]); | 345 size_t sectionIdx = static_cast<size_t>(section); |
| 324 return [[_partitionedEntries objectAtIndex:section] count]; | 346 DCHECK_LT(sectionIdx, _partitionedItems.size()); |
| 347 return _partitionedItems[sectionIdx].size(); |
| 325 } | 348 } |
| 326 | 349 |
| 327 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView | 350 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView |
| 328 cellForItemAtIndexPath:(NSIndexPath*)indexPath { | 351 cellForItemAtIndexPath:(NSIndexPath*)indexPath { |
| 329 TabHistoryCell* cell = | 352 TabHistoryCell* cell = |
| 330 [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier | 353 [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier |
| 331 forIndexPath:indexPath]; | 354 forIndexPath:indexPath]; |
| 332 | 355 cell.item = [self itemAtIndexPath:indexPath]; |
| 333 [cell setEntry:[self entryForIndexPath:indexPath]]; | 356 cell.tag = IDC_BACK_FORWARD_IN_TAB_HISTORY; |
| 334 [cell setTag:IDC_BACK_FORWARD_IN_TAB_HISTORY]; | |
| 335 | |
| 336 return cell; | 357 return cell; |
| 337 } | 358 } |
| 338 | 359 |
| 339 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)view { | 360 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)view { |
| 340 return [_partitionedEntries count]; | 361 return _partitionedItems.size(); |
| 341 } | 362 } |
| 342 | 363 |
| 343 - (UICollectionReusableView*)collectionView:(UICollectionView*)view | 364 - (UICollectionReusableView*)collectionView:(UICollectionView*)view |
| 344 viewForSupplementaryElementOfKind:(NSString*)kind | 365 viewForSupplementaryElementOfKind:(NSString*)kind |
| 345 atIndexPath:(NSIndexPath*)indexPath { | 366 atIndexPath:(NSIndexPath*)indexPath { |
| 367 // Return a footer cell if requested. |
| 346 if ([kind isEqualToString:UICollectionElementKindSectionFooter]) { | 368 if ([kind isEqualToString:UICollectionElementKindSectionFooter]) { |
| 347 return [view dequeueReusableSupplementaryViewOfKind:kind | 369 return [view dequeueReusableSupplementaryViewOfKind:kind |
| 348 withReuseIdentifier:footerIdentifier | 370 withReuseIdentifier:kFooterIdentifier |
| 349 forIndexPath:indexPath]; | 371 forIndexPath:indexPath]; |
| 350 } | 372 } |
| 373 DCHECK([kind isEqualToString:UICollectionElementKindSectionHeader]); |
| 351 | 374 |
| 352 DCHECK([kind isEqualToString:UICollectionElementKindSectionHeader]); | 375 // Dequeue a header cell and populate its favicon image. |
| 353 CRWSessionEntry* sessionEntry = [self entryForIndexPath:indexPath]; | |
| 354 web::NavigationItem* navigationItem = [sessionEntry navigationItem]; | |
| 355 | |
| 356 TabHistorySectionHeader* header = | 376 TabHistorySectionHeader* header = |
| 357 [view dequeueReusableSupplementaryViewOfKind:kind | 377 [view dequeueReusableSupplementaryViewOfKind:kind |
| 358 withReuseIdentifier:headerIdentifier | 378 withReuseIdentifier:kHeaderIdentifier |
| 359 forIndexPath:indexPath]; | 379 forIndexPath:indexPath]; |
| 360 | |
| 361 UIImage* iconImage = nil; | 380 UIImage* iconImage = nil; |
| 362 const gfx::Image& image = navigationItem->GetFavicon().image; | 381 const gfx::Image& image = |
| 382 [self itemAtIndexPath:indexPath]->GetFavicon().image; |
| 363 if (!image.IsEmpty()) | 383 if (!image.IsEmpty()) |
| 364 iconImage = image.ToUIImage(); | 384 iconImage = image.ToUIImage(); |
| 365 else | 385 else |
| 366 iconImage = [UIImage imageNamed:@"default_favicon"]; | 386 iconImage = [UIImage imageNamed:@"default_favicon"]; |
| 367 | |
| 368 [[header iconView] setImage:iconImage]; | 387 [[header iconView] setImage:iconImage]; |
| 369 | 388 |
| 370 return header; | 389 return header; |
| 371 } | 390 } |
| 372 | 391 |
| 373 - (void)setSessionEntries:(NSArray*)sessionEntries { | |
| 374 _sessionEntries = sessionEntries; | |
| 375 | |
| 376 std::string previousHost; | |
| 377 | |
| 378 NSMutableArray* sectionArray = [NSMutableArray array]; | |
| 379 NSMutableArray* partitionedEntries = [NSMutableArray array]; | |
| 380 | |
| 381 NSInteger numberOfEntries = [_sessionEntries count]; | |
| 382 for (NSInteger index = 0; index < numberOfEntries; ++index) { | |
| 383 CRWSessionEntry* sessionEntry = [_sessionEntries objectAtIndex:index]; | |
| 384 web::NavigationItem* navigationItem = [sessionEntry navigationItem]; | |
| 385 | |
| 386 std::string currentHost; | |
| 387 if (navigationItem) | |
| 388 currentHost = navigationItem->GetURL().host(); | |
| 389 | |
| 390 if (previousHost.empty()) | |
| 391 previousHost = currentHost; | |
| 392 | |
| 393 // TODO: This should use some sort of Top Level Domain matching instead of | |
| 394 // explicit host match so that images.googe.com matches shopping.google.com. | |
| 395 if (previousHost == currentHost) { | |
| 396 [sectionArray addObject:sessionEntry]; | |
| 397 } else { | |
| 398 [partitionedEntries addObject:sectionArray]; | |
| 399 sectionArray = [NSMutableArray arrayWithObject:sessionEntry]; | |
| 400 previousHost = currentHost; | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 if ([sectionArray count]) | |
| 405 [partitionedEntries addObject:sectionArray]; | |
| 406 | |
| 407 if (![partitionedEntries count]) | |
| 408 partitionedEntries = nil; | |
| 409 | |
| 410 _partitionedEntries = partitionedEntries; | |
| 411 } | |
| 412 | |
| 413 #pragma mark MDCInkTouchControllerDelegate | 392 #pragma mark MDCInkTouchControllerDelegate |
| 414 | 393 |
| 415 - (BOOL)inkTouchController:(MDCInkTouchController*)inkTouchController | 394 - (BOOL)inkTouchController:(MDCInkTouchController*)inkTouchController |
| 416 shouldProcessInkTouchesAtTouchLocation:(CGPoint)location { | 395 shouldProcessInkTouchesAtTouchLocation:(CGPoint)location { |
| 417 NSIndexPath* indexPath = | 396 NSIndexPath* indexPath = |
| 418 [self.collectionView indexPathForItemAtPoint:location]; | 397 [self.collectionView indexPathForItemAtPoint:location]; |
| 419 TabHistoryCell* cell = base::mac::ObjCCastStrict<TabHistoryCell>( | 398 TabHistoryCell* cell = base::mac::ObjCCastStrict<TabHistoryCell>( |
| 420 [self.collectionView cellForItemAtIndexPath:indexPath]); | 399 [self.collectionView cellForItemAtIndexPath:indexPath]); |
| 421 if (!cell) { | 400 if (!cell) { |
| 422 return NO; | 401 return NO; |
| 423 } | 402 } |
| 424 | 403 |
| 425 // Increase the size of the ink view to cover the collection view from edge | 404 // Increase the size of the ink view to cover the collection view from edge |
| 426 // to edge. | 405 // to edge. |
| 427 CGRect inkViewFrame = [cell frame]; | 406 CGRect inkViewFrame = [cell frame]; |
| 428 inkViewFrame.origin.x = 0; | 407 inkViewFrame.origin.x = 0; |
| 429 inkViewFrame.size.width = CGRectGetWidth([self.collectionView bounds]); | 408 inkViewFrame.size.width = CGRectGetWidth([self.collectionView bounds]); |
| 430 [[inkTouchController defaultInkView] setFrame:inkViewFrame]; | 409 [[inkTouchController defaultInkView] setFrame:inkViewFrame]; |
| 431 return YES; | 410 return YES; |
| 432 } | 411 } |
| 433 | 412 |
| 413 #pragma mark - |
| 414 |
| 415 - (const web::NavigationItem*)itemAtIndexPath:(NSIndexPath*)indexPath { |
| 416 size_t section = static_cast<size_t>([indexPath section]); |
| 417 size_t item = static_cast<size_t>([indexPath item]); |
| 418 DCHECK_LT(section, _partitionedItems.size()); |
| 419 DCHECK_LT(item, _partitionedItems[section].size()); |
| 420 return _partitionedItems[section][item]; |
| 421 } |
| 422 |
| 423 - (void)clearNavigationItems { |
| 424 _partitionedItems.clear(); |
| 425 for (UICollectionViewCell* cell in self.collectionView.visibleCells) { |
| 426 TabHistoryCell* historyCell = base::mac::ObjCCast<TabHistoryCell>(cell); |
| 427 historyCell.item = nullptr; |
| 428 } |
| 429 } |
| 430 |
| 434 @end | 431 @end |
| OLD | NEW |