blob: 29b37f9bb4ddc781129f5f1601ea61129b80b0f0 [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.
package org.chromium.chrome.browser.toolbar;
import android.content.res.Resources;
import android.view.View.OnClickListener;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
import org.chromium.chrome.browser.compositor.layouts.ToolbarSwipeLayout;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchObserver;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
import org.chromium.chrome.browser.gsa.GSAContextDisplaySelection;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.base.WindowAndroid.KeyboardVisibilityListener;
import org.chromium.ui.resources.ResourceManager;
import javax.annotation.Nullable;
/**
* This class is responsible for reacting to events from the outside world, interacting with other
* coordinators, running most of the business logic associated with the bottom toolbar, and updating
* the model accordingly.
*/
class BottomToolbarMediator implements ContextualSearchObserver, FullscreenListener,
KeyboardVisibilityListener, OverviewModeObserver,
SceneChangeObserver {
/** The model for the bottom toolbar that holds all of its state. */
private BottomToolbarModel mModel;
/** The fullscreen manager to observe browser controls events. */
private ChromeFullscreenManager mFullscreenManager;
/** The overview mode manager. */
private OverviewModeBehavior mOverviewModeBehavior;
/** The manager for Contextual Search to observe appearance/disappearance of the feature. */
private ContextualSearchManager mContextualSearchManger;
/** A {@link WindowAndroid} for watching keyboard visibility events. */
private WindowAndroid mWindowAndroid;
/** The previous height of the bottom toolbar. */
private int mBottomToolbarHeightBeforeHide;
/** Whether the swipe layout is currently active. */
private boolean mIsInSwipeLayout;
/**
* Build a new mediator that handles events from outside the bottom toolbar.
* @param model The {@link BottomToolbarModel} that holds all the state for the bottom toolbar.
* @param fullscreenManager A {@link ChromeFullscreenManager} for events related to the browser
* controls.
* @param resources Android {@link Resources} to pull dimensions from.
*/
BottomToolbarMediator(BottomToolbarModel model, ChromeFullscreenManager fullscreenManager,
Resources resources) {
mModel = model;
mFullscreenManager = fullscreenManager;
mFullscreenManager.addListener(this);
// Notify the fullscreen manager that the bottom controls now have a height.
fullscreenManager.setBottomControlsHeight(
resources.getDimensionPixelOffset(R.dimen.bottom_toolbar_height));
fullscreenManager.updateViewportSize();
}
/**
* @param swipeHandler The handler that controls the toolbar swipe behavior.
*/
void setToolbarSwipeHandler(EdgeSwipeHandler swipeHandler) {
mModel.setValue(BottomToolbarModel.TOOLBAR_SWIPE_HANDLER, swipeHandler);
}
/**
* Clean up anything that needs to be when the bottom toolbar is destroyed.
*/
void destroy() {
mFullscreenManager.removeListener(this);
if (mContextualSearchManger != null) mContextualSearchManger.removeObserver(this);
if (mOverviewModeBehavior != null) mOverviewModeBehavior.removeOverviewModeObserver(this);
if (mWindowAndroid != null) mWindowAndroid.removeKeyboardVisibilityListener(this);
if (mModel.getValue(BottomToolbarModel.LAYOUT_MANAGER) != null) {
mModel.getValue(BottomToolbarModel.LAYOUT_MANAGER).removeSceneChangeObserver(this);
}
}
@Override
public void onContentOffsetChanged(float offset) {}
@Override
public void onControlsOffsetChanged(float topOffset, float bottomOffset, boolean needsAnimate) {
mModel.setValue(BottomToolbarModel.Y_OFFSET, (int) bottomOffset);
if (bottomOffset > 0) {
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, false);
} else {
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, true);
}
}
@Override
public void onToggleOverlayVideoMode(boolean enabled) {}
@Override
public void onBottomControlsHeightChanged(int bottomControlsHeight) {}
@Override
public void onOverviewModeStartedShowing(boolean showToolbar) {
mModel.setValue(BottomToolbarModel.SEARCH_ACCELERATOR_VISIBLE, false);
}
@Override
public void onOverviewModeFinishedShowing() {}
@Override
public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
mModel.setValue(BottomToolbarModel.SEARCH_ACCELERATOR_VISIBLE, true);
}
@Override
public void onOverviewModeFinishedHiding() {}
@Override
public void onShowContextualSearch(@Nullable GSAContextDisplaySelection selectionContext) {
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, false);
}
@Override
public void onHideContextualSearch() {
// If the scroll offset for the toolbar is non-zero, it needs to remain hidden after
// contextual search is hidden.
if (mModel.getValue(BottomToolbarModel.Y_OFFSET) != 0) return;
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, true);
}
void setSearchAcceleratorListener(OnClickListener searchAcceleratorListener) {
mModel.setValue(BottomToolbarModel.SEARCH_ACCELERATOR_LISTENER, searchAcceleratorListener);
}
@Override
public void keyboardVisibilityChanged(boolean isShowing) {
// The toolbars are force shown when the keyboard is visible, so we can blindly set
// the bottom toolbar view to visible or invisible regardless of the previous state.
ChromeFullscreenManager fullscreenManager =
mModel.getValue(BottomToolbarModel.LAYOUT_MANAGER).getFullscreenManager();
if (isShowing) {
mBottomToolbarHeightBeforeHide = fullscreenManager.getBottomControlsHeight();
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, false);
mModel.setValue(BottomToolbarModel.COMPOSITED_VIEW_VISIBLE, false);
fullscreenManager.setBottomControlsHeight(0);
} else {
fullscreenManager.setBottomControlsHeight(mBottomToolbarHeightBeforeHide);
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, true);
mModel.setValue(BottomToolbarModel.COMPOSITED_VIEW_VISIBLE, true);
}
}
void setLayoutManager(LayoutManager layoutManager) {
mModel.setValue(BottomToolbarModel.LAYOUT_MANAGER, layoutManager);
layoutManager.addSceneChangeObserver(this);
}
@Override
public void onTabSelectionHinted(int tabId) {}
@Override
public void onSceneChange(Layout layout) {
if (layout instanceof ToolbarSwipeLayout) {
mIsInSwipeLayout = true;
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, false);
} else if (mIsInSwipeLayout) {
// Only change to visible if leaving the swipe layout.
mIsInSwipeLayout = false;
mModel.setValue(BottomToolbarModel.ANDROID_VIEW_VISIBLE, true);
}
}
void setResourceManager(ResourceManager resourceManager) {
mModel.setValue(BottomToolbarModel.RESOURCE_MANAGER, resourceManager);
}
void setOverviewModeBehavior(OverviewModeBehavior overviewModeBehavior) {
mOverviewModeBehavior = overviewModeBehavior;
mOverviewModeBehavior.addOverviewModeObserver(this);
}
void setContextualSearchManager(ContextualSearchManager contextualSearchManager) {
mContextualSearchManger = contextualSearchManager;
if (mContextualSearchManger == null) return;
mContextualSearchManger.addObserver(this);
}
void setToolbarSwipeLayout(ToolbarSwipeLayout layout) {
mModel.setValue(BottomToolbarModel.TOOLBAR_SWIPE_LAYOUT, layout);
}
void setWindowAndroid(WindowAndroid windowAndroid) {
assert mWindowAndroid == null : "#setWindowAndroid should only be called once per toolbar.";
// Watch for keyboard events so we can hide the bottom toolbar when the keyboard is showing.
mWindowAndroid = windowAndroid;
mWindowAndroid.addKeyboardVisibilityListener(this);
}
}