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

Unified Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.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_controller.mm
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..07f5ea19ec6af4daeecf976561edc24c3b34c92b
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_controller.mm
@@ -0,0 +1,335 @@
+// 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_controller.h"
+
+#include "base/logging.h"
+#import "base/mac/scoped_nsobject.h"
+#include "base/strings/sys_string_conversions.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#include "ios/chrome/browser/ui/ntp/recent_tabs/synced_sessions.h"
+#import "ios/chrome/browser/ui/tab_switcher/session_changes.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_view.h"
+
+namespace {
+
+void FillVectorWithHashesUsingDistantSession(
+ synced_sessions::DistantSession const& session,
+ std::vector<size_t>* hashes) {
+ DCHECK(hashes);
+ DCHECK(hashes->empty());
+ for (size_t i = 0; i < session.tabs.size(); ++i) {
+ hashes->push_back(session.tabs[i]->hashOfUserVisibleProperties());
+ }
+}
+
+} // namespace
+
+@interface TabSwitcherPanelController ()<UICollectionViewDataSource,
+ SessionCellDelegate> {
+ ios::ChromeBrowserState* _browserState; // Weak.
+ base::scoped_nsobject<TabSwitcherPanelView> _panelView;
+ base::scoped_nsobject<TabSwitcherModel> _model;
+ std::string _sessionTag;
+ ios_internal::SessionType _sessionType;
+ base::scoped_nsobject<TabSwitcherCache> _cache;
+ base::scoped_nsobject<TabSwitcherPanelOverlayView> _overlayView;
+ std::unique_ptr<const synced_sessions::DistantSession> _distantSession;
+ std::unique_ptr<const TabModelSnapshot> _localSession;
+}
+
+// Changes the visibility of the zero tab state overlay view.
+- (void)setZeroTabStateOverlayVisible:(BOOL)show;
+
+@end
+
+@implementation TabSwitcherPanelController
+
+@synthesize delegate = _delegate;
+@synthesize sessionType = _sessionType;
+
+- (instancetype)initWithModel:(TabSwitcherModel*)model
+ forDistantSessionWithTag:(std::string const&)sessionTag
+ browserState:(ios::ChromeBrowserState*)browserState {
+ self = [super init];
+ if (self) {
+ DCHECK(model);
+ _sessionType = ios_internal::SessionType::DISTANT_SESSION;
+ _model.reset([model retain]);
+ _distantSession = [model distantSessionForTag:sessionTag];
+ _sessionTag = sessionTag;
+ _browserState = browserState;
+ [self loadView];
+ }
+ return self;
+}
+
+- (instancetype)initWithModel:(TabSwitcherModel*)model
+ forLocalSessionOfType:(ios_internal::SessionType)sessionType
+ withCache:(TabSwitcherCache*)cache
+ browserState:(ios::ChromeBrowserState*)browserState {
+ self = [super init];
+ if (self) {
+ DCHECK(model);
+ _sessionType = sessionType;
+ _model.reset([model retain]);
+ _localSession = [model tabModelSnapshotForLocalSession:sessionType];
+ _cache.reset([cache retain]);
+ _browserState = browserState;
+ [self loadView];
+ }
+ return self;
+}
+
+- (TabSwitcherPanelView*)view {
+ return _panelView;
+}
+
+- (std::string)sessionTag {
+ return _sessionTag;
+}
+
+- (void)setDelegate:(id<TabSwitcherPanelControllerDelegate>)delegate {
+ _delegate = delegate;
+ [[_panelView collectionView] performBatchUpdates:nil completion:nil];
+}
+
+- (BOOL)shouldShowNewTabButton {
+ if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
+ return NO;
+ } else {
+ return ![self isOverlayVisible];
+ }
+}
+
+- (void)updateCollectionViewIfNeeded {
+ if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
+ UICollectionView* collectionView = [_panelView collectionView];
+ // TODO(crbug.com/633928) Compute SessionChanges outside of the
+ // updateBlock.
+ auto updateBlock = ^{
+ std::unique_ptr<const synced_sessions::DistantSession> newDistantSession =
+ [_model distantSessionForTag:_sessionTag];
+ std::vector<size_t> oldTabsHashes;
+ std::vector<size_t> newTabsHashes;
+ FillVectorWithHashesUsingDistantSession(*_distantSession.get(),
+ &oldTabsHashes);
+ FillVectorWithHashesUsingDistantSession(*newDistantSession.get(),
+ &newTabsHashes);
+ ios_internal::SessionChanges changes(oldTabsHashes, newTabsHashes);
+ if (changes.hasChanges()) {
+ _distantSession = std::move(newDistantSession);
+ [self applyChanges:changes toCollectionView:collectionView];
+ }
+ };
+ [collectionView performBatchUpdates:updateBlock completion:nil];
+ } else {
+ UICollectionView* collectionView = [_panelView collectionView];
+ auto updateBlock = ^{
+ std::unique_ptr<const TabModelSnapshot> newLocalSession =
+ [_model tabModelSnapshotForLocalSession:_sessionType];
+ ios_internal::SessionChanges changes(_localSession->hashes(),
+ newLocalSession->hashes());
+ if (changes.hasChanges()) {
+ _localSession = std::move(newLocalSession);
+ [self applyChanges:changes toCollectionView:collectionView];
+ }
+ };
+ [collectionView performBatchUpdates:updateBlock completion:nil];
+ }
+}
+
+- (void)applyChanges:(ios_internal::SessionChanges&)changes
+ toCollectionView:(UICollectionView*)collectionView {
+ NSMutableArray* deletedIndexes = [NSMutableArray array];
+ NSMutableArray* insertedIndexes = [NSMutableArray array];
+ NSMutableArray* updatedIndexes = [NSMutableArray array];
+ for (size_t i : changes.deletions()) {
+ NSInteger deletedTabIndex = static_cast<NSInteger>(i);
+ [deletedIndexes
+ addObject:[NSIndexPath indexPathForItem:deletedTabIndex inSection:0]];
+ }
+ for (size_t i : changes.insertions()) {
+ NSInteger insertedTabIndex = static_cast<NSInteger>(i);
+ [insertedIndexes
+ addObject:[NSIndexPath indexPathForItem:insertedTabIndex inSection:0]];
+ }
+ for (size_t i : changes.updates()) {
+ NSInteger updatedTabIndex = static_cast<NSInteger>(i);
+ [updatedIndexes
+ addObject:[NSIndexPath indexPathForItem:updatedTabIndex inSection:0]];
+ }
+ [collectionView deleteItemsAtIndexPaths:deletedIndexes];
+ [collectionView insertItemsAtIndexPaths:insertedIndexes];
+ [collectionView reloadItemsAtIndexPaths:updatedIndexes];
+}
+
+- (void)scrollTabIndexToVisible:(NSInteger)index triggerLayout:(BOOL)layout {
+ [[_panelView collectionView]
+ scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]
+ atScrollPosition:UICollectionViewScrollPositionTop
+ animated:NO];
+ if (layout)
+ [[_panelView collectionView] layoutIfNeeded];
+}
+
+- (TabSwitcherLocalSessionCell*)localSessionCellForTabAtIndex:(NSInteger)index {
+ return (TabSwitcherLocalSessionCell*)[[_panelView collectionView]
+ cellForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
+}
+
+- (CGRect)localSessionCellFrameForTabAtIndex:(NSInteger)index {
+ UICollectionViewLayoutAttributes* attributes = [[_panelView collectionView]
+ layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index
+ inSection:0]];
+ return attributes.frame;
+}
+
+- (void)reload {
+ [[_panelView collectionView] reloadSections:[NSIndexSet indexSetWithIndex:0]];
+}
+
+- (UICollectionView*)collectionView {
+ return [_panelView collectionView];
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)collectionView:(UICollectionView*)collectionView
+ numberOfItemsInSection:(NSInteger)section {
+ DCHECK_EQ(section, 0);
+ if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
+ CHECK(_distantSession);
+ return _distantSession->tabs.size();
+ } else {
+ CHECK(_localSession);
+ NSInteger numberOfTabs = _localSession->tabs().size();
+ [self setZeroTabStateOverlayVisible:numberOfTabs == 0];
+ return numberOfTabs;
+ }
+}
+
+- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
+ cellForItemAtIndexPath:(NSIndexPath*)indexPath {
+ UICollectionViewCell* cell = nil;
+ NSUInteger tabIndex = indexPath.item;
+ if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
+ cell = [collectionView
+ dequeueReusableCellWithReuseIdentifier:[TabSwitcherDistantSessionCell
+ identifier]
+ forIndexPath:indexPath];
+ DCHECK([cell isKindOfClass:[TabSwitcherDistantSessionCell class]]);
+ TabSwitcherDistantSessionCell* panelCell =
+ static_cast<TabSwitcherDistantSessionCell*>(cell);
+ CHECK(_distantSession);
+ const std::size_t distantSessionTabCount = _distantSession->tabs.size();
+ LOG_ASSERT(tabIndex < distantSessionTabCount)
+ << "tabIndex == " << tabIndex
+ << " _distantSession->tabs.size() == " << distantSessionTabCount;
+ synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get();
+ CHECK(tab);
+ [panelCell setTitle:SysUTF16ToNSString(tab->title)];
+ [panelCell setSessionGURL:tab->virtual_url
+ withBrowserState:[_model browserState]];
+ [panelCell setDelegate:self];
+ } else {
+ cell = [collectionView
+ dequeueReusableCellWithReuseIdentifier:[TabSwitcherLocalSessionCell
+ identifier]
+ forIndexPath:indexPath];
+ DCHECK([cell isKindOfClass:[TabSwitcherLocalSessionCell class]]);
+ TabSwitcherLocalSessionCell* panelCell =
+ static_cast<TabSwitcherLocalSessionCell*>(cell);
+ Tab* tab = _localSession->tabs()[tabIndex];
+ [panelCell setDelegate:self];
+ [panelCell setSessionType:_sessionType];
+ [panelCell setAppearanceForTab:tab cellSize:[_panelView cellSize]];
+ }
+ return cell;
+}
+
+#pragma mark - SessionCellDelegate
+
+- (TabSwitcherCache*)tabSwitcherCache {
+ return _cache;
+}
+
+- (void)cellPressed:(UICollectionViewCell*)cell {
+ const NSInteger tabIndex =
+ [[_panelView collectionView] indexPathForCell:cell].item;
+
+ if (_sessionType == ios_internal::SessionType::DISTANT_SESSION) {
+ synced_sessions::DistantTab* tab = _distantSession->tabs[tabIndex].get();
+ if (tab)
+ [self.delegate tabSwitcherPanelController:self didSelectDistantTab:tab];
+ } else {
+ Tab* tab = _localSession->tabs()[tabIndex];
+ if (tab)
+ [self.delegate tabSwitcherPanelController:self didSelectLocalTab:tab];
+ }
+}
+
+- (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell {
+ DCHECK(_sessionType != ios_internal::SessionType::DISTANT_SESSION);
+ const NSInteger tabIndex =
+ [[_panelView collectionView] indexPathForCell:cell].item;
+ Tab* tab = _localSession->tabs()[tabIndex];
+ if (tab)
+ [self.delegate tabSwitcherPanelController:self didCloseLocalTab:tab];
+}
+
+#pragma mark - Private
+
+- (BOOL)isOverlayVisible {
+ return _overlayView && [_overlayView alpha] != 0.0;
+}
+
+- (void)setZeroTabStateOverlayVisible:(BOOL)show {
+ if (show == [self isOverlayVisible])
+ return;
+
+ DCHECK(ios_internal::IsLocalSession(_sessionType));
+
+ if (!_overlayView) {
+ _overlayView.reset([[TabSwitcherPanelOverlayView alloc]
+ initWithFrame:[_panelView bounds]
+ browserState:_browserState]);
+ [_overlayView
+ setOverlayType:
+ (_sessionType == ios_internal::SessionType::OFF_THE_RECORD_SESSION)
+ ? TabSwitcherPanelOverlayType::
+ OVERLAY_PANEL_USER_NO_INCOGNITO_TABS
+ : TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS];
+
+ [_overlayView setAlpha:0];
+ [_overlayView setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
+ UIViewAutoresizingFlexibleWidth];
+ [_panelView addSubview:_overlayView];
+ [_overlayView setNeedsLayout];
+ }
+
+ [UIView
+ animateWithDuration:0.25
+ animations:^{
+ [_overlayView setAlpha:show ? 1.0 : 0.0];
+ [self.delegate
+ tabSwitcherPanelControllerDidUpdateOverlayViewVisibility:
+ self];
+ }];
+}
+
+- (void)loadView {
+ _panelView.reset(
+ [[TabSwitcherPanelView alloc] initWithSessionType:_sessionType]);
+ _panelView.get().collectionView.dataSource = self;
+}
+
+- (synced_sessions::DistantSession const*)distantSession {
+ return _distantSession.get();
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698