Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Unified Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.mm

Issue 2588733002: Upstream Chrome on iOS source code [9/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.mm
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.mm
new file mode 100644
index 0000000000000000000000000000000000000000..08522d91ee1d1767f7e6b701e03a2fda5523ac2f
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.mm
@@ -0,0 +1,153 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+
+namespace {
+const CGFloat minWidthOfTab = 200;
+const CGFloat kInterTabSpacing = 16;
+const UIEdgeInsets kCollectionViewEdgeInsets = {16, 16, 16, 16};
+const CGFloat kMaxSizeAsAFactorOfBounds = 0.5;
+const CGFloat kMinCellHeightWidthRatio = 0.6;
+const CGFloat kMaxCellHeightWidthRatio = 1.8;
+}
+
+@implementation TabSwitcherPanelCollectionViewLayout {
+ // Keeps track of the inserted and deleted index paths.
+ base::scoped_nsobject<NSMutableArray> _deletedIndexPaths;
+ base::scoped_nsobject<NSMutableArray> _insertedIndexPaths;
+}
+
+- (int)maxRowCountWithColumnCount:(int)columnCount inBounds:(CGSize)boundsSize {
+ int cellWidth = (boundsSize.width / columnCount) - (kInterTabSpacing * 2.0);
+ int minCellHeight = cellWidth * kMinCellHeightWidthRatio;
+ return boundsSize.height / (minCellHeight + (kInterTabSpacing * 2.0));
+}
+
+- (void)updateLayoutWithBounds:(CGSize)boundsSize {
+ // Ignore initial call to |updateLayoutWithBounds| when the frame of the
+ // collection view is CGRectZero, because it creates very small cells with
+ // broken constraints.
+ if (boundsSize.height == 0 && boundsSize.width == 0)
+ return;
+ int tabCount = [[self collectionView] numberOfItemsInSection:0];
+ // Early return because there's nothing to layout.
+ if (tabCount == 0)
+ return;
+
+ int numberOfColumns = 0;
+ int numberOfRows = 0;
+
+ int maxNumberOfColums = static_cast<int>(
+ floor(boundsSize.width / (minWidthOfTab + kInterTabSpacing * 2.0)));
+ // No need to have more columns than tabs.
+ maxNumberOfColums = std::min(maxNumberOfColums, tabCount);
+
+ if ([self maxRowCountWithColumnCount:maxNumberOfColums inBounds:boundsSize] *
+ maxNumberOfColums <
+ tabCount) {
+ // It is impossible for all the tabs to be shown on screen at once.
+ // Layout the tabs using the highest density possible, i.e. using the
+ // maximum number of columns.
+ numberOfColumns = maxNumberOfColums;
+ numberOfRows =
+ [self maxRowCountWithColumnCount:maxNumberOfColums inBounds:boundsSize];
+ } else {
+ // Find the most squarish configuration that allows showing all the tabs.
+ // A squarish configuration is a layout were the number of rows and columns
+ // are roughly equal.
+
+ // |bestScore| contains abs(rowCount - columnCount).
+ // The lower |bestScore| is, the better the configuration is.
+ int bestScore = INT_MAX;
+
+ int loopStart;
+ int loopEnd;
+ int loopDirection;
+ if (boundsSize.width > boundsSize.height) {
+ // In landscape, consider in priority layouts with a large number of
+ // columns.
+ loopStart = maxNumberOfColums;
+ loopEnd = 0;
+ loopDirection = -1;
+ } else {
+ // In landscape, consider in priority layouts with a large number of rows,
+ // i.e. a small number of columns.
+ loopStart = 1;
+ loopEnd = maxNumberOfColums + 1;
+ loopDirection = 1;
+ }
+
+ int columnCountIterator = loopStart;
+ while (columnCountIterator != loopEnd) {
+ // Find the minimum number of rows needed to show |tabCount| tab in
+ // |columnCount| columns.
+ int maxRowCount = [self maxRowCountWithColumnCount:columnCountIterator
+ inBounds:boundsSize];
+ int idealRowCount = static_cast<int>(
+ ceil(static_cast<float>(tabCount) / columnCountIterator));
+ if (idealRowCount <= maxRowCount) {
+ int score = abs(idealRowCount - columnCountIterator);
+ if (score < bestScore) {
+ bestScore = score;
+ numberOfColumns = columnCountIterator;
+ numberOfRows = idealRowCount;
+ }
+ }
+ columnCountIterator += loopDirection;
+ }
+ DCHECK_NE(bestScore, INT_MAX);
+ }
+
+ DCHECK_NE(numberOfColumns, 0);
+ DCHECK_NE(numberOfRows, 0);
+
+ // Compute the size of the cells.
+ CGFloat horizontalFreeSpace =
+ boundsSize.width - (kInterTabSpacing * 2 * (numberOfColumns - 1)) -
+ kCollectionViewEdgeInsets.left - kCollectionViewEdgeInsets.right;
+ CGFloat verticalFreeSpace =
+ boundsSize.height - (kInterTabSpacing * 2 * (numberOfRows - 1)) -
+ kCollectionViewEdgeInsets.top - kCollectionViewEdgeInsets.bottom;
+ CGSize newCellSize = CGSizeMake(horizontalFreeSpace / numberOfColumns,
+ verticalFreeSpace / numberOfRows);
+
+ // The cells must not be larger than half of the bounds because the @1x
+ // snapshots would look blurry on retina screens.
+ newCellSize.width =
+ std::min(newCellSize.width, boundsSize.width * kMaxSizeAsAFactorOfBounds);
+ newCellSize.height = std::min(newCellSize.height,
+ boundsSize.height * kMaxSizeAsAFactorOfBounds);
+
+ // Avoid having cells be too narrow.
+ newCellSize.height = std::min(newCellSize.height,
+ newCellSize.width * kMaxCellHeightWidthRatio);
+
+ [self setItemSize:newCellSize];
+
+ [self setMinimumInteritemSpacing:kInterTabSpacing];
+ [self setMinimumLineSpacing:kInterTabSpacing * 2];
+
+ bool forceVerticalCentering = numberOfRows == 1;
+ if (forceVerticalCentering) {
+ UIEdgeInsets insets = kCollectionViewEdgeInsets;
+ insets.top = (boundsSize.height - newCellSize.height) / 2.0;
+ insets.bottom = (boundsSize.height - newCellSize.height) / 2.0;
+ [self setSectionInset:insets];
+ } else {
+ [self setSectionInset:kCollectionViewEdgeInsets];
+ }
+}
+
+- (void)prepareLayout {
+ [super prepareLayout];
+ [self updateLayoutWithBounds:[[self collectionView] bounds].size];
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698