blob: f3d4c7f83d4174e984089d42709e34486c05337b [file] [log] [blame]
Daniel Sandler50a53132012-10-24 15:02:27 -04001/*
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
Daniel Sandler08d05e32012-08-08 16:39:54 -040017package com.android.systemui.statusbar.phone;
18
Daniel Sandler08d05e32012-08-08 16:39:54 -040019import android.content.Context;
20import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040021import android.util.Log;
Daniel Sandler08d05e32012-08-08 16:39:54 -040022import android.view.MotionEvent;
Daniel Sandler173bae22012-09-25 14:37:42 -040023import android.view.View;
Daniel Sandler08d05e32012-08-08 16:39:54 -040024import android.widget.FrameLayout;
25
John Spurlockde84f0e2013-06-12 12:41:00 -040026import java.util.ArrayList;
27
Daniel Sandler08d05e32012-08-08 16:39:54 -040028public class PanelBar extends FrameLayout {
Daniel Sandlerbf4aa9d2012-08-15 10:49:28 -040029 public static final boolean DEBUG = false;
Daniel Sandler198a0302012-08-17 16:04:31 -040030 public static final String TAG = PanelBar.class.getSimpleName();
Daniel Sandler08d05e32012-08-08 16:39:54 -040031 public static final void LOG(String fmt, Object... args) {
32 if (!DEBUG) return;
John Spurlockcd686b52013-06-05 10:13:46 -040033 Log.v(TAG, String.format(fmt, args));
Daniel Sandler08d05e32012-08-08 16:39:54 -040034 }
35
Daniel Sandler198a0302012-08-17 16:04:31 -040036 public static final int STATE_CLOSED = 0;
37 public static final int STATE_OPENING = 1;
38 public static final int STATE_OPEN = 2;
39
Daniel Sandler67eab792012-10-02 17:08:23 -040040 PanelHolder mPanelHolder;
41 ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
42 PanelView mTouchingPanel;
Daniel Sandler978f8532012-08-15 15:48:16 -040043 private int mState = STATE_CLOSED;
44 private boolean mTracking;
45
Daniel Sandler67eab792012-10-02 17:08:23 -040046 float mPanelExpandedFractionSum;
47
Daniel Sandler198a0302012-08-17 16:04:31 -040048 public void go(int state) {
Daniel Sandler67eab792012-10-02 17:08:23 -040049 if (DEBUG) LOG("go state: %d -> %d", mState, state);
Daniel Sandler978f8532012-08-15 15:48:16 -040050 mState = state;
51 }
Daniel Sandler08d05e32012-08-08 16:39:54 -040052
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 addPanel(PanelView pv) {
63 mPanels.add(pv);
64 pv.setBar(this);
65 }
66
67 public void setPanelHolder(PanelHolder ph) {
68 if (ph == null) {
John Spurlockcd686b52013-06-05 10:13:46 -040069 Log.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
Daniel Sandler08d05e32012-08-08 16:39:54 -040070 return;
71 }
72 ph.setBar(this);
73 mPanelHolder = ph;
74 final int N = ph.getChildCount();
75 for (int i=0; i<N; i++) {
Daniel Sandlere111ad32012-10-13 15:17:45 -040076 final View v = ph.getChildAt(i);
77 if (v != null && v instanceof PanelView) {
78 addPanel((PanelView) v);
Daniel Sandler08d05e32012-08-08 16:39:54 -040079 }
80 }
81 }
82
83 public float getBarHeight() {
84 return getMeasuredHeight();
85 }
86
Daniel Sandlerefb0faf2012-10-10 14:15:34 -070087 public PanelView selectPanelForTouch(MotionEvent touch) {
Daniel Sandlercf591db2012-08-15 16:11:55 -040088 final int N = mPanels.size();
Daniel Sandlerefb0faf2012-10-10 14:15:34 -070089 return mPanels.get((int)(N * touch.getX() / getMeasuredWidth()));
Daniel Sandlercf591db2012-08-15 16:11:55 -040090 }
91
Daniel Sandler50508132012-08-16 14:10:53 -040092 public boolean panelsEnabled() {
Daniel Sandler1e8feef2012-08-16 11:37:41 -040093 return true;
94 }
95
Daniel Sandler08d05e32012-08-08 16:39:54 -040096 @Override
97 public boolean onTouchEvent(MotionEvent event) {
Daniel Sandler1e8feef2012-08-16 11:37:41 -040098 // Allow subclasses to implement enable/disable semantics
Daniel Sandler2b99a492013-02-05 13:05:44 -050099 if (!panelsEnabled()) {
100 if (event.getAction() == MotionEvent.ACTION_DOWN) {
John Spurlockcd686b52013-06-05 10:13:46 -0400101 Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
Daniel Sandler2b99a492013-02-05 13:05:44 -0500102 (int) event.getX(), (int) event.getY()));
103 }
104 return false;
105 }
Daniel Sandler1e8feef2012-08-16 11:37:41 -0400106
Daniel Sandler08d05e32012-08-08 16:39:54 -0400107 // figure out which panel needs to be talked to here
108 if (event.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700109 final PanelView panel = selectPanelForTouch(event);
110 if (panel == null) {
111 // panel is not there, so we'll eat the gesture
John Spurlockcd686b52013-06-05 10:13:46 -0400112 Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
Daniel Sandler2b99a492013-02-05 13:05:44 -0500113 (int) event.getX(), (int) event.getY()));
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700114 mTouchingPanel = null;
115 return true;
116 }
John Spurlock919adac2012-10-02 16:41:12 -0400117 boolean enabled = panel.isEnabled();
Daniel Sandler67eab792012-10-02 17:08:23 -0400118 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
John Spurlock919adac2012-10-02 16:41:12 -0400119 (enabled ? "" : " (disabled)"));
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700120 if (!enabled) {
121 // panel is disabled, so we'll eat the gesture
John Spurlockcd686b52013-06-05 10:13:46 -0400122 Log.v(TAG, String.format(
Daniel Sandler2b99a492013-02-05 13:05:44 -0500123 "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
124 panel, (int) event.getX(), (int) event.getY()));
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700125 mTouchingPanel = null;
126 return true;
127 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400128 startOpeningPanel(panel);
Daniel Sandler08d05e32012-08-08 16:39:54 -0400129 }
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700130 final boolean result = mTouchingPanel != null
Daniel Sandler040c2e42012-10-17 00:56:33 -0400131 ? mTouchingPanel.onTouchEvent(event)
Daniel Sandlerefb0faf2012-10-10 14:15:34 -0700132 : true;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400133 return result;
134 }
135
Daniel Sandler198a0302012-08-17 16:04:31 -0400136 // called from PanelView when self-expanding, too
137 public void startOpeningPanel(PanelView panel) {
Daniel Sandler67eab792012-10-02 17:08:23 -0400138 if (DEBUG) LOG("startOpeningPanel: " + panel);
Daniel Sandler198a0302012-08-17 16:04:31 -0400139 mTouchingPanel = panel;
140 mPanelHolder.setSelectedPanel(mTouchingPanel);
Daniel Sandler67eab792012-10-02 17:08:23 -0400141 for (PanelView pv : mPanels) {
142 if (pv != panel) {
Jorim Jaggif3b3bee2015-04-16 14:57:34 -0700143 pv.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
Daniel Sandler67eab792012-10-02 17:08:23 -0400144 }
145 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400146 }
147
Jorim Jaggib472b3472014-06-30 19:56:24 +0200148 /**
149 * @param panel the panel which changed its expansion state
150 * @param frac the fraction from the expansion in [0, 1]
151 * @param expanded whether the panel is currently expanded; this is independent from the
152 * fraction as the panel also might be expanded if the fraction is 0
153 */
154 public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) {
Daniel Sandler08d05e32012-08-08 16:39:54 -0400155 boolean fullyClosed = true;
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400156 PanelView fullyOpenedPanel = null;
Daniel Sandler67eab792012-10-02 17:08:23 -0400157 if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
158 mPanelExpandedFractionSum = 0f;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400159 for (PanelView pv : mPanels) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700160 pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler978f8532012-08-15 15:48:16 -0400161 // adjust any other panels that may be partially visible
Jorim Jaggib472b3472014-06-30 19:56:24 +0200162 if (expanded) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400163 if (mState == STATE_CLOSED) {
164 go(STATE_OPENING);
165 onPanelPeeked();
166 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400167 fullyClosed = false;
168 final float thisFrac = pv.getExpandedFraction();
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700169 mPanelExpandedFractionSum += thisFrac;
Daniel Sandler67eab792012-10-02 17:08:23 -0400170 if (DEBUG) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac);
Daniel Sandler08d05e32012-08-08 16:39:54 -0400171 if (panel == pv) {
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400172 if (thisFrac == 1f) fullyOpenedPanel = panel;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400173 }
174 }
175 }
Daniel Sandler67eab792012-10-02 17:08:23 -0400176 mPanelExpandedFractionSum /= mPanels.size();
Daniel Sandler978f8532012-08-15 15:48:16 -0400177 if (fullyOpenedPanel != null && !mTracking) {
178 go(STATE_OPEN);
179 onPanelFullyOpened(fullyOpenedPanel);
Daniel Sandler198a0302012-08-17 16:04:31 -0400180 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
Daniel Sandler978f8532012-08-15 15:48:16 -0400181 go(STATE_CLOSED);
182 onAllPanelsCollapsed();
183 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400184
Daniel Sandler67eab792012-10-02 17:08:23 -0400185 if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400186 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400187 }
188
Jorim Jaggif3b3bee2015-04-16 14:57:34 -0700189 public void collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400190 boolean waiting = false;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400191 for (PanelView pv : mPanels) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400192 if (animate && !pv.isFullyCollapsed()) {
Jorim Jaggif3b3bee2015-04-16 14:57:34 -0700193 pv.collapse(delayed, speedUpFactor);
Daniel Sandler198a0302012-08-17 16:04:31 -0400194 waiting = true;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400195 } else {
Jorim Jaggidbbf45e2014-06-25 21:54:48 +0200196 pv.resetViews();
Daniel Sandler08d05e32012-08-08 16:39:54 -0400197 pv.setExpandedFraction(0); // just in case
John Spurlock97642182013-07-29 17:58:39 -0400198 pv.cancelPeek();
Daniel Sandler08d05e32012-08-08 16:39:54 -0400199 }
200 }
Daniel Sandler67eab792012-10-02 17:08:23 -0400201 if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
Daniel Sandlerc38bbc32012-10-05 12:21:38 -0400202 if (!waiting && mState != STATE_CLOSED) {
John Spurlock209bede2013-07-17 12:23:27 -0400203 // it's possible that nothing animated, so we replicate the termination
Daniel Sandler198a0302012-08-17 16:04:31 -0400204 // conditions of panelExpansionChanged here
205 go(STATE_CLOSED);
206 onAllPanelsCollapsed();
207 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400208 }
209
210 public void onPanelPeeked() {
Daniel Sandler67eab792012-10-02 17:08:23 -0400211 if (DEBUG) LOG("onPanelPeeked");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400212 }
213
214 public void onAllPanelsCollapsed() {
Daniel Sandler67eab792012-10-02 17:08:23 -0400215 if (DEBUG) LOG("onAllPanelsCollapsed");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400216 }
217
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400218 public void onPanelFullyOpened(PanelView openPanel) {
Daniel Sandler67eab792012-10-02 17:08:23 -0400219 if (DEBUG) LOG("onPanelFullyOpened");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400220 }
Daniel Sandler978f8532012-08-15 15:48:16 -0400221
222 public void onTrackingStarted(PanelView panel) {
223 mTracking = true;
Daniel Sandler67eab792012-10-02 17:08:23 -0400224 if (DEBUG && panel != mTouchingPanel) {
Daniel Sandler978f8532012-08-15 15:48:16 -0400225 LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
226 panel, mTouchingPanel);
227 }
228 }
229
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200230 public void onTrackingStopped(PanelView panel, boolean expand) {
Daniel Sandler978f8532012-08-15 15:48:16 -0400231 mTracking = false;
Daniel Sandler978f8532012-08-15 15:48:16 -0400232 }
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200233
234 public void onExpandingFinished() {
235
236 }
Selim Cinekdbbcfbe2014-10-24 17:52:35 +0200237
238 public void onClosingFinished() {
239
240 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400241}