| // 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. |
| |
| package org.chromium.chrome.browser.compositor.bottombar.readermode; |
| |
| import android.content.Context; |
| |
| import org.chromium.chrome.R; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayContentDelegate; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayContentProgressObserver; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContentViewDelegate; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; |
| import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.PanelPriority; |
| import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; |
| import org.chromium.chrome.browser.compositor.scene_layer.ContextualSearchSceneLayer; |
| import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer; |
| import org.chromium.chrome.browser.dom_distiller.ReaderModeManagerDelegate; |
| import org.chromium.content.browser.ContentViewCore; |
| import org.chromium.ui.resources.ResourceManager; |
| |
| /** |
| * The panel containing reader mode. |
| */ |
| public class ReaderModePanel extends OverlayPanel { |
| |
| /** |
| * The compositor layer used for drawing the panel. |
| */ |
| private ContextualSearchSceneLayer mSceneLayer; |
| |
| /** |
| * Delegate for calling functions on the ReaderModeManager. |
| */ |
| private ReaderModeManagerDelegate mManagerDelegate; |
| |
| /** |
| * Delegate for passing the current ContentViewCore to the layout manager. |
| */ |
| private OverlayPanelContentViewDelegate mContentViewDelegate; |
| |
| /** |
| * The opacity of the panel bar text. |
| */ |
| private float mReaderBarTextOpacity; |
| |
| // ============================================================================================ |
| // Constructor |
| // ============================================================================================ |
| |
| /** |
| * @param context The current Android {@link Context}. |
| * @param updateHost The {@link LayoutUpdateHost} used to request updates in the Layout. |
| */ |
| public ReaderModePanel(Context context, LayoutUpdateHost updateHost, |
| OverlayPanelManager panelManager, |
| OverlayPanelContentViewDelegate contentViewDelegate) { |
| super(context, updateHost, panelManager); |
| mSceneLayer = createNewReaderModeSceneLayer(); |
| mContentViewDelegate = contentViewDelegate; |
| } |
| |
| /** |
| * Destroy the panel's components. |
| */ |
| public void destroy() { |
| super.destroy(); |
| destroyReaderModeBarControl(); |
| } |
| |
| @Override |
| public OverlayPanelContent createNewOverlayPanelContent() { |
| OverlayContentDelegate delegate = new OverlayContentDelegate() { |
| @Override |
| public void onContentViewCreated(ContentViewCore contentView) { |
| mContentViewDelegate.setOverlayPanelContentViewCore(contentView); |
| } |
| |
| @Override |
| public void onContentViewDestroyed() { |
| mContentViewDelegate.releaseOverlayPanelContentViewCore(); |
| } |
| |
| @Override |
| public void onMainFrameNavigation(String url, boolean isExternalUrl, |
| boolean isFailure) { |
| if (isExternalUrl) { |
| mManagerDelegate.createNewTab(url); |
| } |
| } |
| }; |
| |
| return new OverlayPanelContent(delegate, new OverlayContentProgressObserver(), mActivity); |
| } |
| |
| // ============================================================================================ |
| // Scene layer |
| // ============================================================================================ |
| |
| @Override |
| public SceneLayer getSceneLayer() { |
| return mSceneLayer; |
| } |
| |
| @Override |
| public void updateSceneLayer(ResourceManager resourceManager) { |
| if (mSceneLayer == null) return; |
| |
| // This will cause the ContentViewCore to size itself appropriately for the panel (includes |
| // top controls height). |
| updateTopControlsState(); |
| |
| // TODO(mdjones): Uncomment this when other changes have merged! |
| //mSceneLayer.update(resourceManager, this, |
| // 0, getBarTextViewId(), null, 0, mReaderBarTextOpacity, null); |
| } |
| |
| /** |
| * Create a new scene layer for this panel. This should be overridden by tests as necessary. |
| */ |
| protected ContextualSearchSceneLayer createNewReaderModeSceneLayer() { |
| return new ContextualSearchSceneLayer(mContext.getResources().getDisplayMetrics().density); |
| } |
| |
| // ============================================================================================ |
| // Manager Integration |
| // ============================================================================================ |
| |
| /** |
| * Sets the {@code ReaderModeManagerDelegate} associated with this panel. |
| * @param delegate The {@code ReaderModeManagerDelegate}. |
| */ |
| public void setManagerDelegate(ReaderModeManagerDelegate delegate) { |
| // TODO(mdjones): This looks similar to setManagementDelegate in ContextualSearchPanel, |
| // consider moving this to OverlayPanel. |
| if (mManagerDelegate != delegate) { |
| mManagerDelegate = delegate; |
| if (mManagerDelegate != null) { |
| setChromeActivity(mManagerDelegate.getChromeActivity()); |
| initializeUiState(); |
| updateBasePageTargetY(); |
| } |
| } |
| } |
| |
| // ============================================================================================ |
| // Generic Event Handling |
| // ============================================================================================ |
| |
| @Override |
| public void handleBarClick(long time, float x, float y) { |
| super.handleBarClick(time, x, y); |
| if (isCoordinateInsideCloseButton(x, y)) { |
| closePanel(StateChangeReason.CLOSE_BUTTON, true); |
| mManagerDelegate.onCloseButtonPressed(); |
| } else { |
| maximizePanel(StateChangeReason.SEARCH_BAR_TAP); |
| } |
| } |
| |
| @Override |
| public boolean onInterceptBarClick() { |
| // TODO(mdjones): Handle compatibility mode here (promote to tab on tap). |
| return false; |
| } |
| |
| // ============================================================================================ |
| // Panel base methods |
| // ============================================================================================ |
| |
| @Override |
| public PanelPriority getPriority() { |
| return PanelPriority.MEDIUM; |
| } |
| |
| @Override |
| public boolean canBeSuppressed() { |
| return true; |
| } |
| |
| @Override |
| public void peekPanel(StateChangeReason reason) { |
| super.peekPanel(reason); |
| mManagerDelegate.onPanelPeek(); |
| } |
| |
| @Override |
| protected void updatePanelForCloseOrPeek(float percent) { |
| super.updatePanelForCloseOrPeek(percent); |
| getReaderModeBarControl().setBarText(R.string.reader_view_text); |
| mReaderBarTextOpacity = 1.0f; |
| } |
| |
| @Override |
| protected void updatePanelForExpansion(float percent) { |
| super.updatePanelForExpansion(percent); |
| if (percent < 0.5f) { |
| mReaderBarTextOpacity = 1.0f - 2.0f * percent; |
| getReaderModeBarControl().setBarText(R.string.reader_view_text); |
| } else { |
| mReaderBarTextOpacity = 2.0f * (percent - 0.5f); |
| getReaderModeBarControl().setBarText(R.string.reader_mode_expanded_title); |
| } |
| } |
| |
| @Override |
| protected void updatePanelForMaximization(float percent) { |
| super.updatePanelForMaximization(percent); |
| getReaderModeBarControl().setBarText(R.string.reader_mode_expanded_title); |
| mReaderBarTextOpacity = 1.0f; |
| } |
| |
| @Override |
| public float getArrowIconOpacity() { |
| // TODO(mdjones): This will not be needed once Reader Mode has its own scene layer. |
| // Never show the arrow icon. |
| return 0.0f; |
| } |
| |
| @Override |
| public float getCloseIconOpacity() { |
| // TODO(mdjones): Make close button controlled by overlay panel as a toggle. |
| // TODO(mdjones): This will not be needed once Reader Mode has its own scene layer. |
| // Always show the close icon. |
| return 1.0f; |
| } |
| |
| @Override |
| protected float calculateBasePageTargetY(PanelState state) { |
| // TODO(mdjones): Remove this method when this panel behaves like the toolbar. In the case |
| // of reader mode the base page will always need to move the same amount. |
| return -getToolbarHeight(); |
| } |
| |
| // ============================================================================================ |
| // ReaderModeBarControl |
| // ============================================================================================ |
| |
| private ReaderModeBarControl mReaderModeBarControl; |
| |
| /** |
| * @return The Id of the Search Term View. |
| */ |
| public int getBarTextViewId() { |
| return getReaderModeBarControl().getViewId(); |
| } |
| |
| /** |
| * Creates the ReaderModeBarControl, if needed. The Views are set to INVISIBLE, because |
| * they won't actually be displayed on the screen (their snapshots will be displayed instead). |
| */ |
| protected ReaderModeBarControl getReaderModeBarControl() { |
| assert mContainerView != null; |
| assert mResourceLoader != null; |
| |
| if (mReaderModeBarControl == null) { |
| mReaderModeBarControl = |
| new ReaderModeBarControl(this, mContext, mContainerView, mResourceLoader); |
| } |
| |
| assert mReaderModeBarControl != null; |
| return mReaderModeBarControl; |
| } |
| |
| /** |
| * Destroys the ReaderModeBarControl. |
| */ |
| protected void destroyReaderModeBarControl() { |
| if (mReaderModeBarControl != null) { |
| mReaderModeBarControl.destroy(); |
| mReaderModeBarControl = null; |
| } |
| } |
| } |