blob: 7a2d7c7ae4b942ac127c05fe1409db5635615ad6 [file] [log] [blame]
// Copyright 2018 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_grid/tab_grid_coordinator.h"
#import "ios/chrome/browser/tabs/tab_model.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/main/bvc_container_view_controller.h"
#import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h"
#import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h"
#import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h"
#import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface TabGridCoordinator ()
// Commad dispatcher used while this coordinator's view controller is active.
// (for compatibility with the TabSwitcher protocol).
@property(nonatomic, strong) CommandDispatcher* dispatcher;
// Object that internally backs the public TabSwitcher
@property(nonatomic, strong) TabGridAdaptor* adaptor;
// Container view controller for the BVC to live in; this class's view
// controller will present this.
@property(nonatomic, strong) BVCContainerViewController* bvcContainer;
// Transitioning delegate for the view controller.
@property(nonatomic, strong) TabGridTransitionHandler* transitionHandler;
// Mediator for regular Tabs.
@property(nonatomic, strong) TabGridMediator* regularTabsMediator;
// Mediator for incognito Tabs.
@property(nonatomic, strong) TabGridMediator* incognitoTabsMediator;
@end
@implementation TabGridCoordinator
// Superclass property.
@synthesize mainViewController = _mainViewController;
// Public properties.
@synthesize animationsDisabledForTesting = _animationsDisabledForTesting;
@synthesize regularTabModel = _regularTabModel;
@synthesize incognitoTabModel = _incognitoTabModel;
// Private properties.
@synthesize dispatcher = _dispatcher;
@synthesize adaptor = _adaptor;
@synthesize bvcContainer = _bvcContainer;
@synthesize transitionHandler = _transitionHandler;
@synthesize regularTabsMediator = _regularTabsMediator;
@synthesize incognitoTabsMediator = _incognitoTabsMediator;
- (instancetype)initWithWindow:(nullable UIWindow*)window
applicationCommandEndpoint:
(id<ApplicationCommands>)applicationCommandEndpoint {
if ((self = [super initWithWindow:window])) {
_dispatcher = [[CommandDispatcher alloc] init];
[_dispatcher startDispatchingToTarget:self
forProtocol:@protocol(BrowserCommands)];
[_dispatcher startDispatchingToTarget:applicationCommandEndpoint
forProtocol:@protocol(ApplicationCommands)];
}
return self;
}
#pragma mark - Public properties
- (id<TabSwitcher>)tabSwitcher {
return self.adaptor;
}
#pragma mark - MainCoordinator properties
- (id<ViewControllerSwapping>)viewControllerSwapper {
return self;
}
#pragma mark - ChromeCoordinator
- (void)start {
TabGridViewController* mainViewController =
[[TabGridViewController alloc] init];
self.transitionHandler = [[TabGridTransitionHandler alloc] init];
self.transitionHandler.provider = mainViewController;
mainViewController.transitioningDelegate = self.transitionHandler;
_mainViewController = mainViewController;
self.window.rootViewController = self.mainViewController;
self.adaptor = [[TabGridAdaptor alloc] init];
self.adaptor.tabGridViewController = self.mainViewController;
self.adaptor.adaptedDispatcher =
static_cast<id<ApplicationCommands, BrowserCommands, OmniboxFocuser,
ToolbarCommands>>(self.dispatcher);
}
- (void)stop {
[self.dispatcher stopDispatchingForProtocol:@protocol(BrowserCommands)];
[self.dispatcher stopDispatchingForProtocol:@protocol(ApplicationCommands)];
}
#pragma mark - ViewControllerSwapping
- (UIViewController*)activeViewController {
if (self.bvcContainer) {
DCHECK_EQ(self.bvcContainer,
self.mainViewController.presentedViewController);
DCHECK(self.bvcContainer.currentBVC);
return self.bvcContainer.currentBVC;
}
return self.mainViewController;
}
- (UIViewController*)viewController {
return self.mainViewController;
}
- (void)showTabSwitcher:(id<TabSwitcher>)tabSwitcher
completion:(ProceduralBlock)completion {
DCHECK(tabSwitcher);
DCHECK_EQ([tabSwitcher viewController], self.mainViewController);
// It's also expected that |tabSwitcher| will be |self.tabSwitcher|, but that
// may not be worth a DCHECK?
// If a BVC is currently being presented, dismiss it. This will trigger any
// necessary animations.
if (self.bvcContainer) {
self.bvcContainer.transitioningDelegate = self.transitionHandler;
self.bvcContainer = nil;
BOOL animated = !self.animationsDisabledForTesting;
[self.mainViewController dismissViewControllerAnimated:animated
completion:completion];
} else {
if (completion) {
completion();
}
}
}
- (void)showTabViewController:(UIViewController*)viewController
completion:(ProceduralBlock)completion {
DCHECK(viewController);
// If another BVC is already being presented, swap this one into the
// container.
if (self.bvcContainer) {
self.bvcContainer.currentBVC = viewController;
if (completion) {
completion();
}
return;
}
self.bvcContainer = [[BVCContainerViewController alloc] init];
self.bvcContainer.currentBVC = viewController;
self.bvcContainer.transitioningDelegate = self.transitionHandler;
BOOL animated = !self.animationsDisabledForTesting;
// Extened |completion| to also signal the tab switcher delegate
// that the animated "tab switcher dismissal" (that is, presenting something
// on top of the tab switcher) transition has completed.
ProceduralBlock extendedCompletion = ^{
[self.tabSwitcher.delegate
tabSwitcherDismissTransitionDidEnd:self.tabSwitcher];
if (completion) {
completion();
}
};
[self.mainViewController presentViewController:self.bvcContainer
animated:animated
completion:extendedCompletion];
}
#pragma mark - BrowserCommands
- (void)openNewTab:(OpenNewTabCommand*)command {
}
- (void)closeAllTabs {
}
- (void)closeAllIncognitoTabs {
}
@end