Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.statusbar.phone;
     18 
     19 import android.content.Context;
     20 import android.util.AttributeSet;
     21 import android.util.Log;
     22 import android.view.MotionEvent;
     23 import android.view.View;
     24 import android.widget.FrameLayout;
     25 
     26 public abstract class PanelBar extends FrameLayout {
     27     public static final boolean DEBUG = false;
     28     public static final String TAG = PanelBar.class.getSimpleName();
     29     private static final boolean SPEW = false;
     30 
     31     public static final void LOG(String fmt, Object... args) {
     32         if (!DEBUG) return;
     33         Log.v(TAG, String.format(fmt, args));
     34     }
     35 
     36     public static final int STATE_CLOSED = 0;
     37     public static final int STATE_OPENING = 1;
     38     public static final int STATE_OPEN = 2;
     39 
     40     PanelView mPanel;
     41     private int mState = STATE_CLOSED;
     42     private boolean mTracking;
     43 
     44     public void go(int state) {
     45         if (DEBUG) LOG("go state: %d -> %d", mState, state);
     46         mState = state;
     47     }
     48 
     49     public int getState() {
     50         return mState;
     51     }
     52 
     53     public PanelBar(Context context, AttributeSet attrs) {
     54         super(context, attrs);
     55     }
     56 
     57     @Override
     58     protected void onFinishInflate() {
     59         super.onFinishInflate();
     60     }
     61 
     62     public void setPanel(PanelView pv) {
     63         mPanel = pv;
     64         pv.setBar(this);
     65     }
     66 
     67     public void setBouncerShowing(boolean showing) {
     68         int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
     69                 : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
     70 
     71         setImportantForAccessibility(important);
     72 
     73         if (mPanel != null) mPanel.setImportantForAccessibility(important);
     74     }
     75 
     76     public boolean panelEnabled() {
     77         return true;
     78     }
     79 
     80     @Override
     81     public boolean onTouchEvent(MotionEvent event) {
     82         // Allow subclasses to implement enable/disable semantics
     83         if (!panelEnabled()) {
     84             if (event.getAction() == MotionEvent.ACTION_DOWN) {
     85                 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
     86                         (int) event.getX(), (int) event.getY()));
     87             }
     88             return false;
     89         }
     90 
     91         if (event.getAction() == MotionEvent.ACTION_DOWN) {
     92             final PanelView panel = mPanel;
     93             if (panel == null) {
     94                 // panel is not there, so we'll eat the gesture
     95                 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
     96                         (int) event.getX(), (int) event.getY()));
     97                 return true;
     98             }
     99             boolean enabled = panel.isEnabled();
    100             if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
    101                     (enabled ? "" : " (disabled)"));
    102             if (!enabled) {
    103                 // panel is disabled, so we'll eat the gesture
    104                 Log.v(TAG, String.format(
    105                         "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
    106                         panel, (int) event.getX(), (int) event.getY()));
    107                 return true;
    108             }
    109         }
    110         return mPanel == null || mPanel.onTouchEvent(event);
    111     }
    112 
    113     public abstract void panelScrimMinFractionChanged(float minFraction);
    114 
    115     /**
    116      * @param frac the fraction from the expansion in [0, 1]
    117      * @param expanded whether the panel is currently expanded; this is independent from the
    118      *                 fraction as the panel also might be expanded if the fraction is 0
    119      */
    120     public void panelExpansionChanged(float frac, boolean expanded) {
    121         boolean fullyClosed = true;
    122         boolean fullyOpened = false;
    123         if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
    124         PanelView pv = mPanel;
    125         pv.setVisibility(expanded ? VISIBLE : INVISIBLE);
    126         // adjust any other panels that may be partially visible
    127         if (expanded) {
    128             if (mState == STATE_CLOSED) {
    129                 go(STATE_OPENING);
    130                 onPanelPeeked();
    131             }
    132             fullyClosed = false;
    133             final float thisFrac = pv.getExpandedFraction();
    134             if (SPEW) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
    135             fullyOpened = thisFrac >= 1f;
    136         }
    137         if (fullyOpened && !mTracking) {
    138             go(STATE_OPEN);
    139             onPanelFullyOpened();
    140         } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
    141             go(STATE_CLOSED);
    142             onPanelCollapsed();
    143         }
    144 
    145         if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
    146                 fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
    147     }
    148 
    149     public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
    150         boolean waiting = false;
    151         PanelView pv = mPanel;
    152         if (animate && !pv.isFullyCollapsed()) {
    153             pv.collapse(delayed, speedUpFactor);
    154             waiting = true;
    155         } else {
    156             pv.resetViews();
    157             pv.setExpandedFraction(0); // just in case
    158             pv.cancelPeek();
    159         }
    160         if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
    161         if (!waiting && mState != STATE_CLOSED) {
    162             // it's possible that nothing animated, so we replicate the termination
    163             // conditions of panelExpansionChanged here
    164             go(STATE_CLOSED);
    165             onPanelCollapsed();
    166         }
    167     }
    168 
    169     public void onPanelPeeked() {
    170         if (DEBUG) LOG("onPanelPeeked");
    171     }
    172 
    173     public boolean isClosed() {
    174         return mState == STATE_CLOSED;
    175     }
    176 
    177     public void onPanelCollapsed() {
    178         if (DEBUG) LOG("onPanelCollapsed");
    179     }
    180 
    181     public void onPanelFullyOpened() {
    182         if (DEBUG) LOG("onPanelFullyOpened");
    183     }
    184 
    185     public void onTrackingStarted() {
    186         mTracking = true;
    187     }
    188 
    189     public void onTrackingStopped(boolean expand) {
    190         mTracking = false;
    191     }
    192 
    193     public void onExpandingFinished() {
    194         if (DEBUG) LOG("onExpandingFinished");
    195     }
    196 
    197     public void onClosingFinished() {
    198 
    199     }
    200 }
    201