150a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler/*
250a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Copyright (C) 2012 The Android Open Source Project
350a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler *
450a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License");
550a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * you may not use this file except in compliance with the License.
650a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * You may obtain a copy of the License at
750a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler *
850a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler *      http://www.apache.org/licenses/LICENSE-2.0
950a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler *
1050a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Unless required by applicable law or agreed to in writing, software
1150a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS,
1250a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1350a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * See the License for the specific language governing permissions and
1450a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * limitations under the License.
1550a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler */
1650a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler
1708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpackage com.android.systemui.statusbar.phone;
1808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.content.Context;
2008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.util.AttributeSet;
21cd686b5b6d4166b510df8e32138479a9559bc117John Spurlockimport android.util.Log;
2208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.view.MotionEvent;
23173bae2c674b2bc25cf376cbb4e150bd86703049Daniel Sandlerimport android.view.View;
2408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.widget.FrameLayout;
2508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
263d395c69fa67732ceb2c045d03ea81efa3710afaSelim Cinekpublic abstract class PanelBar extends FrameLayout {
27bf4aa9d5bc34df144afcab45e8045d34a0ac090aDaniel Sandler    public static final boolean DEBUG = false;
28198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    public static final String TAG = PanelBar.class.getSimpleName();
291689594851a6dd985cff69913e7f4bc548062808Chris Wren    private static final boolean SPEW = false;
301689594851a6dd985cff69913e7f4bc548062808Chris Wren
3108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public static final void LOG(String fmt, Object... args) {
3208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        if (!DEBUG) return;
33cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock        Log.v(TAG, String.format(fmt, args));
3408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
3508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
36198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    public static final int STATE_CLOSED = 0;
37198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    public static final int STATE_OPENING = 1;
38198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    public static final int STATE_OPEN = 2;
39198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler
409f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    PanelView mPanel;
41978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler    private int mState = STATE_CLOSED;
42978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler    private boolean mTracking;
43978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler
44198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    public void go(int state) {
4567eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler        if (DEBUG) LOG("go state: %d -> %d", mState, state);
46978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler        mState = state;
47978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler    }
4808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
490a7d9f275e6481c36726f058c8af799bc24d5408Jason Monk    public int getState() {
500a7d9f275e6481c36726f058c8af799bc24d5408Jason Monk        return mState;
510a7d9f275e6481c36726f058c8af799bc24d5408Jason Monk    }
520a7d9f275e6481c36726f058c8af799bc24d5408Jason Monk
5308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public PanelBar(Context context, AttributeSet attrs) {
5408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        super(context, attrs);
5508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
5608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
5708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    @Override
5808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    protected void onFinishInflate() {
5908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        super.onFinishInflate();
6008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
6108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
629f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void setPanel(PanelView pv) {
639f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        mPanel = pv;
6408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        pv.setBar(this);
6508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
6608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
67d0b2f7ddcac251acfe88092ecef4abb63b3e248bAdrian Roos    public void setBouncerShowing(boolean showing) {
683531a95aaa956366ff29f0b99691b82c6c3e2045Adrian Roos        int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
693531a95aaa956366ff29f0b99691b82c6c3e2045Adrian Roos                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
703531a95aaa956366ff29f0b99691b82c6c3e2045Adrian Roos
713531a95aaa956366ff29f0b99691b82c6c3e2045Adrian Roos        setImportantForAccessibility(important);
723531a95aaa956366ff29f0b99691b82c6c3e2045Adrian Roos
739f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (mPanel != null) mPanel.setImportantForAccessibility(important);
74d0b2f7ddcac251acfe88092ecef4abb63b3e248bAdrian Roos    }
75d0b2f7ddcac251acfe88092ecef4abb63b3e248bAdrian Roos
769f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public boolean panelEnabled() {
771e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler        return true;
781e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler    }
791e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler
8008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    @Override
8108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public boolean onTouchEvent(MotionEvent event) {
821e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler        // Allow subclasses to implement enable/disable semantics
839f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (!panelEnabled()) {
842b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler            if (event.getAction() == MotionEvent.ACTION_DOWN) {
85cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock                Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
862b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler                        (int) event.getX(), (int) event.getY()));
872b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler            }
882b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler            return false;
892b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler        }
901e8feef1faca7d2f14bf459691dbe724c8cf5c88Daniel Sandler
9108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        if (event.getAction() == MotionEvent.ACTION_DOWN) {
929f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            final PanelView panel = mPanel;
93efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler            if (panel == null) {
94efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler                // panel is not there, so we'll eat the gesture
95cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock                Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
962b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler                        (int) event.getX(), (int) event.getY()));
97efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler                return true;
98efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler            }
99919adac28bd6a9888c3bbd53a1736f260bc76bbfJohn Spurlock            boolean enabled = panel.isEnabled();
10067eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
101919adac28bd6a9888c3bbd53a1736f260bc76bbfJohn Spurlock                    (enabled ? "" : " (disabled)"));
102efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler            if (!enabled) {
103efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler                // panel is disabled, so we'll eat the gesture
104cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock                Log.v(TAG, String.format(
1052b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler                        "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
1062b99a49c2e2dec29d350b662d5b45bca59cfd5c6Daniel Sandler                        panel, (int) event.getX(), (int) event.getY()));
107efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler                return true;
108efb0faf1c043777762eecfef87ec575632c365e1Daniel Sandler            }
10967eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler        }
1109f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        return mPanel == null || mPanel.onTouchEvent(event);
111198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler    }
112198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler
1133d395c69fa67732ceb2c045d03ea81efa3710afaSelim Cinek    public abstract void panelScrimMinFractionChanged(float minFraction);
1143d395c69fa67732ceb2c045d03ea81efa3710afaSelim Cinek
115b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi    /**
116b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi     * @param frac the fraction from the expansion in [0, 1]
117b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi     * @param expanded whether the panel is currently expanded; this is independent from the
118b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi     *                 fraction as the panel also might be expanded if the fraction is 0
119b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi     */
1209f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void panelExpansionChanged(float frac, boolean expanded) {
12108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        boolean fullyClosed = true;
1229f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        boolean fullyOpened = false;
1239f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
1249f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        PanelView pv = mPanel;
12548ff9b48335b6a22795f798ff07c9a6d83078c1cSelim Cinek        pv.setVisibility(expanded ? VISIBLE : INVISIBLE);
1269f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        // adjust any other panels that may be partially visible
1279f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (expanded) {
1289f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            if (mState == STATE_CLOSED) {
1299f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen                go(STATE_OPENING);
1309f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen                onPanelPeeked();
13108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler            }
1329f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            fullyClosed = false;
1339f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            final float thisFrac = pv.getExpandedFraction();
1349f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            if (SPEW) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
1359f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            fullyOpened = thisFrac >= 1f;
13608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        }
1379f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (fullyOpened && !mTracking) {
138978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler            go(STATE_OPEN);
1399f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            onPanelFullyOpened();
140198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
141978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler            go(STATE_CLOSED);
1429f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            onPanelCollapsed();
143978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler        }
14408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1451689594851a6dd985cff69913e7f4bc548062808Chris Wren        if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
1469f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen                fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
14708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
14808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1499f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
150198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler        boolean waiting = false;
1519f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        PanelView pv = mPanel;
1529f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (animate && !pv.isFullyCollapsed()) {
1539f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            pv.collapse(delayed, speedUpFactor);
1549f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            waiting = true;
1559f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        } else {
1569f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            pv.resetViews();
1579f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            pv.setExpandedFraction(0); // just in case
1589f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            pv.cancelPeek();
15908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        }
1609f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
161c38bbc391ae4ec5945d5fa408da3994552f775ebDaniel Sandler        if (!waiting && mState != STATE_CLOSED) {
162209bede6b9edb9171e5bee4077b48e35004a37b4John Spurlock            // it's possible that nothing animated, so we replicate the termination
163198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler            // conditions of panelExpansionChanged here
164198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler            go(STATE_CLOSED);
1659f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen            onPanelCollapsed();
166198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler        }
16708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
16808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
16908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public void onPanelPeeked() {
17067eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler        if (DEBUG) LOG("onPanelPeeked");
17108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
17208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
173aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk    public boolean isClosed() {
174aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk        return mState == STATE_CLOSED;
175aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk    }
176aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk
1779f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void onPanelCollapsed() {
1789f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen        if (DEBUG) LOG("onPanelCollapsed");
17908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
18008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1819f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void onPanelFullyOpened() {
18267eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler        if (DEBUG) LOG("onPanelFullyOpened");
18308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
184978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler
1859f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void onTrackingStarted() {
186978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler        mTracking = true;
187978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler    }
188978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler
1899f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen    public void onTrackingStopped(boolean expand) {
190978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler        mTracking = false;
191978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler    }
1922fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi
1932fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi    public void onExpandingFinished() {
1941689594851a6dd985cff69913e7f4bc548062808Chris Wren        if (DEBUG) LOG("onExpandingFinished");
1952fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi    }
196dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek
197dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek    public void onClosingFinished() {
198dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek
199dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek    }
20008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler}
201