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