/* * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.android.browser; import android.graphics.Bitmap; import android.os.AsyncTask; import android.support.v4.widget.ViewDragHelper; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Toast; public class EdgeSwipeSettings extends ViewDragHelper.Callback { private ViewDragHelper mDragHelper; private int mFromEdge = ViewDragHelper.EDGE_TOP; private int mLeft = 0; private ImageView mSlidingViewShadow; private LinearLayout mSettingsView; private DraggableFrameLayout mViewGroup; private View mLiveView; private ImageView mStationaryView; private int mSlidingViewIndex; private int mCurrIndex; private EdgeSwipeModel mModel; private Tab mActiveTab; private TitleBar mTitleBar; private boolean mbWaitForSettings = false; public EdgeSwipeSettings(final View container, int stationaryViewId, int settingViewId, int slidingViewShadowId, int liveViewId, int viewGroupId, final BaseUi ui) { DraggableFrameLayout viewGroup = (DraggableFrameLayout) container.findViewById(viewGroupId); mSlidingViewShadow = (ImageView) container.findViewById(slidingViewShadowId); mSettingsView = (LinearLayout) container.findViewById(settingViewId); mStationaryView = (ImageView) container.findViewById(stationaryViewId); mLiveView = container.findViewById(liveViewId); mViewGroup = (DraggableFrameLayout) container.findViewById(viewGroupId); final int childCount = mViewGroup.getChildCount(); for (int i = childCount - 1; i >= 0; i--) { final View child = mViewGroup.getChildAt(i); if (mSettingsView == child) { mSlidingViewIndex = i; break; } } mActiveTab = ui.getActiveTab(); mTitleBar = ui.getTitleBar(); mModel = new EdgeSwipeModel(mActiveTab, mTitleBar); mDragHelper = ViewDragHelper.create(viewGroup, 0.5f, this); mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT | ViewDragHelper.EDGE_RIGHT); mViewGroup.setDragHelper(mDragHelper); final Button closeBtn = (Button) container.findViewById(R.id.edge_sliding_settings_close_btn); closeBtn.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { goLive(); } } ); final RadioButton temporalNavButton = (RadioButton) container.findViewById(R.id.edge_sliding_settings_options_temporal); temporalNavButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { BrowserSettings.getInstance().setEdgeSwipeTemporal(); goLive(); applySettingsAndRefresh(ui, container); Toast toast = Toast.makeText(ui.getActivity().getApplicationContext(), R.string.pref_temporal_edge_swipe_enabled_toast, Toast.LENGTH_SHORT); toast.show(); } } ); final RadioButton spatialNavButton = (RadioButton) container.findViewById(R.id.edge_sliding_settings_options_spatial); spatialNavButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { BrowserSettings.getInstance().setEdgeSwipeSpatial(); goLive(); applySettingsAndRefresh(ui, container); Toast toast = Toast.makeText(ui.getActivity().getApplicationContext(), R.string.pref_spatial_edge_swipe_enabled_toast, Toast.LENGTH_SHORT); toast.show(); } } ); final RadioButton disabledNavButton = (RadioButton) container.findViewById(R.id.edge_sliding_settings_options_disabled); disabledNavButton.setOnClickListener( new View.OnClickListener() { public void onClick(View v) { BrowserSettings.getInstance().setEdgeSwipeDisabled(); goLive(); applySettingsAndRefresh(ui, container); Toast toast = Toast.makeText(ui.getActivity().getApplicationContext(), R.string.pref_edge_swipe_disabled_toast, Toast.LENGTH_SHORT); toast.show(); } } ); } private void applySettingsAndRefresh(final BaseUi ui, final View container) { new AsyncTask() { @Override protected Void doInBackground(Void... unused) { mDragHelper = null; ui.refreshEdgeSwipeController(container); return null; } }.execute(); } private void goLive() { mbWaitForSettings = false; mFromEdge = ViewDragHelper.EDGE_TOP; mLiveView.setVisibility(View.VISIBLE); mStationaryView.setVisibility(View.GONE); mSlidingViewShadow.setVisibility(View.GONE); mSettingsView.setVisibility(View.GONE); mViewGroup.postInvalidate(); } private void goDormant() { mLiveView.setVisibility(View.GONE); mStationaryView.setVisibility(View.VISIBLE); mViewGroup.invalidate(); } public void onConfigurationChanged() { goLive(); } public void cleanup() { synchronized (this) { goLive(); mModel.cleanup(); } } private void showCurrBitmap() { if (mStationaryView.getVisibility() == View.VISIBLE) { return; } Bitmap currBM = mModel.readSnapshot(mCurrIndex); if (currBM != null) { clampViewIfNeeded(mStationaryView); mStationaryView.setImageBitmap(currBM); goDormant(); mModel.deleteSnapshot(mCurrIndex); } } private void clampViewIfNeeded(View view) { int offset = 0; if (mTitleBar.getY() >= 0) { offset = mTitleBar.getNavigationBar().getMeasuredHeight(); } view.setPadding(0, offset - view.getTop(), 0, 0); } public void onViewDragStateChanged(int state) { if (ViewDragHelper.STATE_IDLE == state && !mbWaitForSettings) { goLive(); } } public void onViewReleased(View releasedChild, float xvel, float yvel) { boolean bCrossedEventHorizon = Math.abs(mLeft) > mViewGroup.getWidth() / 2; switch (mFromEdge) { case ViewDragHelper.EDGE_LEFT: if (xvel > 0 || (xvel == 0 && mLeft > 0 && bCrossedEventHorizon)) { showCurrBitmap(); mbWaitForSettings = true; mDragHelper.settleCapturedViewAt( releasedChild.getMeasuredWidth(), releasedChild.getTop()); break; } mDragHelper.settleCapturedViewAt(0, releasedChild.getTop()); break; case ViewDragHelper.EDGE_RIGHT: if (xvel < 0 || (xvel == 0 && mLeft < 0 && bCrossedEventHorizon)) { showCurrBitmap(); mbWaitForSettings = true; mDragHelper.settleCapturedViewAt( -releasedChild.getMeasuredWidth(), releasedChild.getTop()); break; } mDragHelper.settleCapturedViewAt(0, releasedChild.getTop()); break; default: mDragHelper.settleCapturedViewAt(0, releasedChild.getTop()); break; } mLeft = 0; mViewGroup.invalidate(); } public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { showCurrBitmap(); switch (mFromEdge) { case ViewDragHelper.EDGE_LEFT: mSlidingViewShadow.setX(left); mViewGroup.invalidate(); break; case ViewDragHelper.EDGE_RIGHT: mSlidingViewShadow.setX(mViewGroup.getMeasuredWidth() + left - mSlidingViewShadow.getMeasuredWidth()); mViewGroup.invalidate(); break; default: break; } } public void onEdgeDragStarted(int edgeFlags, int pointerId) { if (mFromEdge != ViewDragHelper.EDGE_TOP) { return; } mCurrIndex = mActiveTab.getWebView().copyBackForwardList().getCurrentIndex(); mModel.updateSnapshot(mCurrIndex); clampViewIfNeeded(mSettingsView); if (ViewDragHelper.EDGE_LEFT == (edgeFlags & ViewDragHelper.EDGE_LEFT)) { mFromEdge = ViewDragHelper.EDGE_LEFT; mSettingsView.setTranslationX(-mViewGroup.getMeasuredWidth()); mSlidingViewShadow.setBackgroundResource(R.drawable.right_shade); } else if (ViewDragHelper.EDGE_RIGHT == (edgeFlags & ViewDragHelper.EDGE_RIGHT)) { mFromEdge = ViewDragHelper.EDGE_RIGHT; mSettingsView.setTranslationX(mViewGroup.getMeasuredWidth()); mSlidingViewShadow.setBackgroundResource(R.drawable.left_shade); } mSettingsView.setVisibility(View.VISIBLE); mSlidingViewShadow.setVisibility(View.VISIBLE); showCurrBitmap(); mViewGroup.invalidate(); } public int getOrderedChildIndex(int index) { return mSlidingViewIndex; } public int getViewHorizontalDragRange(View child) { return child.getMeasuredWidth(); } public boolean tryCaptureView(View child, int pointerId) { return (mFromEdge != ViewDragHelper.EDGE_TOP && child == mSettingsView); } public int clampViewPositionHorizontal(View child, int left, int dx) { mLeft = left; return left; } }