blob: 496219996b747e8a312c4a797cdb574b5847f7c3 [file] [log] [blame]
Daniel Sandler08d05e32012-08-08 16:39:54 -04001package com.android.systemui.statusbar.phone;
2
3import java.util.ArrayList;
4
5import android.content.Context;
6import android.util.AttributeSet;
7import android.util.Slog;
8import android.view.MotionEvent;
Daniel Sandler173bae22012-09-25 14:37:42 -04009import android.view.View;
Daniel Sandler08d05e32012-08-08 16:39:54 -040010import android.widget.FrameLayout;
11
12public class PanelBar extends FrameLayout {
Daniel Sandlerbf4aa9d2012-08-15 10:49:28 -040013 public static final boolean DEBUG = false;
Daniel Sandler198a0302012-08-17 16:04:31 -040014 public static final String TAG = PanelBar.class.getSimpleName();
Daniel Sandler08d05e32012-08-08 16:39:54 -040015 public static final void LOG(String fmt, Object... args) {
16 if (!DEBUG) return;
17 Slog.v(TAG, String.format(fmt, args));
18 }
19
Daniel Sandler198a0302012-08-17 16:04:31 -040020 public static final int STATE_CLOSED = 0;
21 public static final int STATE_OPENING = 1;
22 public static final int STATE_OPEN = 2;
23
Daniel Sandler67eab792012-10-02 17:08:23 -040024 PanelHolder mPanelHolder;
25 ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
26 PanelView mTouchingPanel;
Daniel Sandler978f8532012-08-15 15:48:16 -040027 private int mState = STATE_CLOSED;
28 private boolean mTracking;
29
Daniel Sandler67eab792012-10-02 17:08:23 -040030 float mPanelExpandedFractionSum;
31
Daniel Sandler198a0302012-08-17 16:04:31 -040032 public void go(int state) {
Daniel Sandler67eab792012-10-02 17:08:23 -040033 if (DEBUG) LOG("go state: %d -> %d", mState, state);
Daniel Sandler978f8532012-08-15 15:48:16 -040034 mState = state;
35 }
Daniel Sandler08d05e32012-08-08 16:39:54 -040036
37 public PanelBar(Context context, AttributeSet attrs) {
38 super(context, attrs);
39 }
40
41 @Override
42 protected void onFinishInflate() {
43 super.onFinishInflate();
44 }
45
46 public void addPanel(PanelView pv) {
47 mPanels.add(pv);
48 pv.setBar(this);
49 }
50
51 public void setPanelHolder(PanelHolder ph) {
52 if (ph == null) {
53 Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
54 return;
55 }
56 ph.setBar(this);
57 mPanelHolder = ph;
58 final int N = ph.getChildCount();
59 for (int i=0; i<N; i++) {
60 final PanelView v = (PanelView) ph.getChildAt(i);
61 if (v != null) {
62 addPanel(v);
63 }
64 }
65 }
66
67 public float getBarHeight() {
68 return getMeasuredHeight();
69 }
70
Daniel Sandlercf591db2012-08-15 16:11:55 -040071 public PanelView selectPanelForTouchX(float x) {
72 final int N = mPanels.size();
73 return mPanels.get((int)(N * x / getMeasuredWidth()));
74 }
75
Daniel Sandler50508132012-08-16 14:10:53 -040076 public boolean panelsEnabled() {
Daniel Sandler1e8feef2012-08-16 11:37:41 -040077 return true;
78 }
79
Daniel Sandler08d05e32012-08-08 16:39:54 -040080 @Override
81 public boolean onTouchEvent(MotionEvent event) {
Daniel Sandler1e8feef2012-08-16 11:37:41 -040082 // Allow subclasses to implement enable/disable semantics
Daniel Sandler50508132012-08-16 14:10:53 -040083 if (!panelsEnabled()) return false;
Daniel Sandler1e8feef2012-08-16 11:37:41 -040084
Daniel Sandler08d05e32012-08-08 16:39:54 -040085 // figure out which panel needs to be talked to here
86 if (event.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandler198a0302012-08-17 16:04:31 -040087 final PanelView panel = selectPanelForTouchX(event.getX());
John Spurlock919adac2012-10-02 16:41:12 -040088 boolean enabled = panel.isEnabled();
Daniel Sandler67eab792012-10-02 17:08:23 -040089 if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
John Spurlock919adac2012-10-02 16:41:12 -040090 (enabled ? "" : " (disabled)"));
91 if (!enabled)
92 return false;
Daniel Sandler198a0302012-08-17 16:04:31 -040093 startOpeningPanel(panel);
Daniel Sandler08d05e32012-08-08 16:39:54 -040094 }
95 final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
96 return result;
97 }
98
Daniel Sandler198a0302012-08-17 16:04:31 -040099 // called from PanelView when self-expanding, too
100 public void startOpeningPanel(PanelView panel) {
Daniel Sandler67eab792012-10-02 17:08:23 -0400101 if (DEBUG) LOG("startOpeningPanel: " + panel);
Daniel Sandler198a0302012-08-17 16:04:31 -0400102 mTouchingPanel = panel;
103 mPanelHolder.setSelectedPanel(mTouchingPanel);
Daniel Sandler67eab792012-10-02 17:08:23 -0400104 for (PanelView pv : mPanels) {
105 if (pv != panel) {
106 pv.collapse();
107 }
108 }
Daniel Sandler198a0302012-08-17 16:04:31 -0400109 }
110
Daniel Sandler08d05e32012-08-08 16:39:54 -0400111 public void panelExpansionChanged(PanelView panel, float frac) {
112 boolean fullyClosed = true;
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400113 PanelView fullyOpenedPanel = null;
Daniel Sandler67eab792012-10-02 17:08:23 -0400114 if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
115 mPanelExpandedFractionSum = 0f;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400116 for (PanelView pv : mPanels) {
Daniel Sandler173bae22012-09-25 14:37:42 -0400117 final boolean visible = pv.getVisibility() == View.VISIBLE;
Daniel Sandler978f8532012-08-15 15:48:16 -0400118 // adjust any other panels that may be partially visible
Daniel Sandler08d05e32012-08-08 16:39:54 -0400119 if (pv.getExpandedHeight() > 0f) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400120 if (mState == STATE_CLOSED) {
121 go(STATE_OPENING);
122 onPanelPeeked();
123 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400124 fullyClosed = false;
125 final float thisFrac = pv.getExpandedFraction();
Daniel Sandler67eab792012-10-02 17:08:23 -0400126 mPanelExpandedFractionSum += (visible ? thisFrac : 0);
127 if (DEBUG) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac);
Daniel Sandler08d05e32012-08-08 16:39:54 -0400128 if (panel == pv) {
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400129 if (thisFrac == 1f) fullyOpenedPanel = panel;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400130 }
131 }
Daniel Sandler173bae22012-09-25 14:37:42 -0400132 if (pv.getExpandedHeight() > 0f) {
133 if (!visible) pv.setVisibility(View.VISIBLE);
134 } else {
135 if (visible) pv.setVisibility(View.GONE);
136 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400137 }
Daniel Sandler67eab792012-10-02 17:08:23 -0400138 mPanelExpandedFractionSum /= mPanels.size();
Daniel Sandler978f8532012-08-15 15:48:16 -0400139 if (fullyOpenedPanel != null && !mTracking) {
140 go(STATE_OPEN);
141 onPanelFullyOpened(fullyOpenedPanel);
Daniel Sandler198a0302012-08-17 16:04:31 -0400142 } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
Daniel Sandler978f8532012-08-15 15:48:16 -0400143 go(STATE_CLOSED);
144 onAllPanelsCollapsed();
145 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400146
Daniel Sandler67eab792012-10-02 17:08:23 -0400147 if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400148 (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400149 }
150
151 public void collapseAllPanels(boolean animate) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400152 boolean waiting = false;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400153 for (PanelView pv : mPanels) {
Daniel Sandler198a0302012-08-17 16:04:31 -0400154 if (animate && !pv.isFullyCollapsed()) {
155 pv.collapse();
156 waiting = true;
Daniel Sandler08d05e32012-08-08 16:39:54 -0400157 } else {
158 pv.setExpandedFraction(0); // just in case
Daniel Sandler67eab792012-10-02 17:08:23 -0400159 pv.setVisibility(View.GONE);
Daniel Sandler08d05e32012-08-08 16:39:54 -0400160 }
161 }
Daniel Sandler67eab792012-10-02 17:08:23 -0400162 if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
Daniel Sandler198a0302012-08-17 16:04:31 -0400163 if (!waiting) {
164 // it's possible that nothing animated, so we replicate the termination
165 // conditions of panelExpansionChanged here
166 go(STATE_CLOSED);
167 onAllPanelsCollapsed();
168 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400169 }
170
171 public void onPanelPeeked() {
Daniel Sandler67eab792012-10-02 17:08:23 -0400172 if (DEBUG) LOG("onPanelPeeked");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400173 }
174
175 public void onAllPanelsCollapsed() {
Daniel Sandler67eab792012-10-02 17:08:23 -0400176 if (DEBUG) LOG("onAllPanelsCollapsed");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400177 }
178
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400179 public void onPanelFullyOpened(PanelView openPanel) {
Daniel Sandler67eab792012-10-02 17:08:23 -0400180 if (DEBUG) LOG("onPanelFullyOpened");
Daniel Sandler08d05e32012-08-08 16:39:54 -0400181 }
Daniel Sandler978f8532012-08-15 15:48:16 -0400182
183 public void onTrackingStarted(PanelView panel) {
184 mTracking = true;
Daniel Sandler67eab792012-10-02 17:08:23 -0400185 if (DEBUG && panel != mTouchingPanel) {
Daniel Sandler978f8532012-08-15 15:48:16 -0400186 LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
187 panel, mTouchingPanel);
188 }
189 }
190
191 public void onTrackingStopped(PanelView panel) {
192 mTracking = false;
193 panelExpansionChanged(panel, panel.getExpandedFraction());
194 }
Daniel Sandler08d05e32012-08-08 16:39:54 -0400195}