• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static java.lang.Float.isNaN;
20 
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.os.Parcelable;
24 import android.util.AttributeSet;
25 import android.util.Log;
26 import android.view.MotionEvent;
27 import android.widget.FrameLayout;
28 
29 public abstract class PanelBar extends FrameLayout {
30     public static final boolean DEBUG = false;
31     public static final String TAG = PanelBar.class.getSimpleName();
32     private static final boolean SPEW = false;
33     private static final String PANEL_BAR_SUPER_PARCELABLE = "panel_bar_super_parcelable";
34     private static final String STATE = "state";
35     private boolean mBouncerShowing;
36     private boolean mExpanded;
37     protected float mPanelFraction;
38 
LOG(String fmt, Object... args)39     public static final void LOG(String fmt, Object... args) {
40         if (!DEBUG) return;
41         Log.v(TAG, String.format(fmt, args));
42     }
43 
44     public static final int STATE_CLOSED = 0;
45     public static final int STATE_OPENING = 1;
46     public static final int STATE_OPEN = 2;
47 
48     PanelViewController mPanel;
49     private int mState = STATE_CLOSED;
50     private boolean mTracking;
51 
go(int state)52     public void go(int state) {
53         if (DEBUG) LOG("go state: %d -> %d", mState, state);
54         mState = state;
55         if (mPanel != null) {
56             mPanel.setIsShadeOpening(state == STATE_OPENING);
57         }
58     }
59 
isShadeOpening()60     protected boolean isShadeOpening() {
61         return mState == STATE_OPENING;
62     }
63 
64     @Override
onSaveInstanceState()65     protected Parcelable onSaveInstanceState() {
66         Bundle bundle = new Bundle();
67         bundle.putParcelable(PANEL_BAR_SUPER_PARCELABLE, super.onSaveInstanceState());
68         bundle.putInt(STATE, mState);
69         return bundle;
70     }
71 
72     @Override
onRestoreInstanceState(Parcelable state)73     protected void onRestoreInstanceState(Parcelable state) {
74         if (state == null || !(state instanceof Bundle)) {
75             super.onRestoreInstanceState(state);
76             return;
77         }
78 
79         Bundle bundle = (Bundle) state;
80         super.onRestoreInstanceState(bundle.getParcelable(PANEL_BAR_SUPER_PARCELABLE));
81         if (((Bundle) state).containsKey(STATE)) {
82             go(bundle.getInt(STATE, STATE_CLOSED));
83         }
84     }
85 
PanelBar(Context context, AttributeSet attrs)86     public PanelBar(Context context, AttributeSet attrs) {
87         super(context, attrs);
88     }
89 
90     @Override
onFinishInflate()91     protected void onFinishInflate() {
92         super.onFinishInflate();
93     }
94 
95     /** Set the PanelViewController */
setPanel(PanelViewController pv)96     public void setPanel(PanelViewController pv) {
97         mPanel = pv;
98         pv.setBar(this);
99     }
100 
setBouncerShowing(boolean showing)101     public void setBouncerShowing(boolean showing) {
102         mBouncerShowing = showing;
103         int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
104                 : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
105 
106         setImportantForAccessibility(important);
107         updateVisibility();
108 
109         if (mPanel != null) mPanel.getView().setImportantForAccessibility(important);
110     }
111 
getExpansionFraction()112     public float getExpansionFraction() {
113         return mPanelFraction;
114     }
115 
isExpanded()116     public boolean isExpanded() {
117         return mExpanded;
118     }
119 
updateVisibility()120     protected void updateVisibility() {
121         mPanel.getView().setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
122     }
123 
shouldPanelBeVisible()124     protected boolean shouldPanelBeVisible() {
125         return mExpanded || mBouncerShowing;
126     }
127 
panelEnabled()128     public boolean panelEnabled() {
129         return true;
130     }
131 
132     @Override
onTouchEvent(MotionEvent event)133     public boolean onTouchEvent(MotionEvent event) {
134         // Allow subclasses to implement enable/disable semantics
135         if (!panelEnabled()) {
136             if (event.getAction() == MotionEvent.ACTION_DOWN) {
137                 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
138                         (int) event.getX(), (int) event.getY()));
139             }
140             return false;
141         }
142 
143         if (event.getAction() == MotionEvent.ACTION_DOWN) {
144             final PanelViewController panel = mPanel;
145             if (panel == null) {
146                 // panel is not there, so we'll eat the gesture
147                 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
148                         (int) event.getX(), (int) event.getY()));
149                 return true;
150             }
151             boolean enabled = panel.isEnabled();
152             if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
153                     (enabled ? "" : " (disabled)"));
154             if (!enabled) {
155                 // panel is disabled, so we'll eat the gesture
156                 Log.v(TAG, String.format(
157                         "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
158                         panel, (int) event.getX(), (int) event.getY()));
159                 return true;
160             }
161         }
162         return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
163     }
164 
panelScrimMinFractionChanged(float minFraction)165     public abstract void panelScrimMinFractionChanged(float minFraction);
166 
167     /**
168      * @param frac the fraction from the expansion in [0, 1]
169      * @param expanded whether the panel is currently expanded; this is independent from the
170      *                 fraction as the panel also might be expanded if the fraction is 0
171      */
panelExpansionChanged(float frac, boolean expanded)172     public void panelExpansionChanged(float frac, boolean expanded) {
173         if (isNaN(frac)) {
174             throw new IllegalArgumentException("frac cannot be NaN");
175         }
176         boolean fullyClosed = true;
177         boolean fullyOpened = false;
178         if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
179         PanelViewController pv = mPanel;
180         mExpanded = expanded;
181         mPanelFraction = frac;
182         updateVisibility();
183         // adjust any other panels that may be partially visible
184         if (expanded) {
185             if (mState == STATE_CLOSED) {
186                 go(STATE_OPENING);
187                 onPanelPeeked();
188             }
189             fullyClosed = false;
190             final float thisFrac = pv.getExpandedFraction();
191             if (SPEW) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
192             fullyOpened = thisFrac >= 1f;
193         }
194         if (fullyOpened && !mTracking) {
195             go(STATE_OPEN);
196             onPanelFullyOpened();
197         } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
198             go(STATE_CLOSED);
199             onPanelCollapsed();
200         }
201 
202         if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
203                 fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
204     }
205 
collapsePanel(boolean animate, boolean delayed, float speedUpFactor)206     public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
207         boolean waiting = false;
208         PanelViewController pv = mPanel;
209         if (animate && !pv.isFullyCollapsed()) {
210             pv.collapse(delayed, speedUpFactor);
211             waiting = true;
212         } else {
213             pv.resetViews(false /* animate */);
214             pv.setExpandedFraction(0); // just in case
215         }
216         if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
217         if (!waiting && mState != STATE_CLOSED) {
218             // it's possible that nothing animated, so we replicate the termination
219             // conditions of panelExpansionChanged here
220             go(STATE_CLOSED);
221             onPanelCollapsed();
222         }
223     }
224 
onPanelPeeked()225     public void onPanelPeeked() {
226         if (DEBUG) LOG("onPanelPeeked");
227     }
228 
isClosed()229     public boolean isClosed() {
230         return mState == STATE_CLOSED;
231     }
232 
onPanelCollapsed()233     public void onPanelCollapsed() {
234         if (DEBUG) LOG("onPanelCollapsed");
235     }
236 
onPanelFullyOpened()237     public void onPanelFullyOpened() {
238         if (DEBUG) LOG("onPanelFullyOpened");
239     }
240 
onTrackingStarted()241     public void onTrackingStarted() {
242         mTracking = true;
243     }
244 
onTrackingStopped(boolean expand)245     public void onTrackingStopped(boolean expand) {
246         mTracking = false;
247     }
248 
onExpandingFinished()249     public void onExpandingFinished() {
250         if (DEBUG) LOG("onExpandingFinished");
251     }
252 
onClosingFinished()253     public void onClosingFinished() {
254 
255     }
256 }
257