PanelBar.java revision 040c2e4ace25a45bc701821da4fa786e6dd75ead
1package 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;
9import android.view.View;
10import android.widget.FrameLayout;
11
12public class PanelBar extends FrameLayout {
13    public static final boolean DEBUG = false;
14    public static final String TAG = PanelBar.class.getSimpleName();
15    public static final void LOG(String fmt, Object... args) {
16        if (!DEBUG) return;
17        Slog.v(TAG, String.format(fmt, args));
18    }
19
20    public static final int STATE_CLOSED = 0;
21    public static final int STATE_OPENING = 1;
22    public static final int STATE_OPEN = 2;
23
24    PanelHolder mPanelHolder;
25    ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
26    PanelView mTouchingPanel;
27    private int mState = STATE_CLOSED;
28    private boolean mTracking;
29
30    float mPanelExpandedFractionSum;
31
32    public void go(int state) {
33        if (DEBUG) LOG("go state: %d -> %d", mState, state);
34        mState = state;
35    }
36
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 View v = ph.getChildAt(i);
61            if (v != null && v instanceof PanelView) {
62                addPanel((PanelView) v);
63            }
64        }
65    }
66
67    public float getBarHeight() {
68        return getMeasuredHeight();
69    }
70
71    public PanelView selectPanelForTouch(MotionEvent touch) {
72        final int N = mPanels.size();
73        return mPanels.get((int)(N * touch.getX() / getMeasuredWidth()));
74    }
75
76    public boolean panelsEnabled() {
77        return true;
78    }
79
80    @Override
81    public boolean onTouchEvent(MotionEvent event) {
82        // Allow subclasses to implement enable/disable semantics
83        if (!panelsEnabled()) return false;
84
85        // figure out which panel needs to be talked to here
86        if (event.getAction() == MotionEvent.ACTION_DOWN) {
87            final PanelView panel = selectPanelForTouch(event);
88            if (panel == null) {
89                // panel is not there, so we'll eat the gesture
90                if (DEBUG) LOG("PanelBar.onTouch: no panel for x=%d, bailing", event.getX());
91                mTouchingPanel = null;
92                return true;
93            }
94            boolean enabled = panel.isEnabled();
95            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
96                    (enabled ? "" : " (disabled)"));
97            if (!enabled) {
98                // panel is disabled, so we'll eat the gesture
99                mTouchingPanel = null;
100                return true;
101            }
102            startOpeningPanel(panel);
103        }
104        final boolean result = mTouchingPanel != null
105                ? mTouchingPanel.onTouchEvent(event)
106                : true;
107        return result;
108    }
109
110    // called from PanelView when self-expanding, too
111    public void startOpeningPanel(PanelView panel) {
112        if (DEBUG) LOG("startOpeningPanel: " + panel);
113        mTouchingPanel = panel;
114        mPanelHolder.setSelectedPanel(mTouchingPanel);
115        for (PanelView pv : mPanels) {
116            if (pv != panel) {
117                pv.collapse();
118            }
119        }
120    }
121
122    public void panelExpansionChanged(PanelView panel, float frac) {
123        boolean fullyClosed = true;
124        PanelView fullyOpenedPanel = null;
125        if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
126        mPanelExpandedFractionSum = 0f;
127        for (PanelView pv : mPanels) {
128            final boolean visible = pv.getVisibility() == View.VISIBLE;
129            // adjust any other panels that may be partially visible
130            if (pv.getExpandedHeight() > 0f) {
131                if (mState == STATE_CLOSED) {
132                    go(STATE_OPENING);
133                    onPanelPeeked();
134                }
135                fullyClosed = false;
136                final float thisFrac = pv.getExpandedFraction();
137                mPanelExpandedFractionSum += (visible ? thisFrac : 0);
138                if (DEBUG) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
139                if (panel == pv) {
140                    if (thisFrac == 1f) fullyOpenedPanel = panel;
141                }
142            }
143            if (pv.getExpandedHeight() > 0f) {
144                if (!visible) pv.setVisibility(View.VISIBLE);
145            } else {
146                if (visible) pv.setVisibility(View.GONE);
147            }
148        }
149        mPanelExpandedFractionSum /= mPanels.size();
150        if (fullyOpenedPanel != null && !mTracking) {
151            go(STATE_OPEN);
152            onPanelFullyOpened(fullyOpenedPanel);
153        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
154            go(STATE_CLOSED);
155            onAllPanelsCollapsed();
156        }
157
158        if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
159                (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
160    }
161
162    public void collapseAllPanels(boolean animate) {
163        boolean waiting = false;
164        for (PanelView pv : mPanels) {
165            if (animate && !pv.isFullyCollapsed()) {
166                pv.collapse();
167                waiting = true;
168            } else {
169                pv.setExpandedFraction(0); // just in case
170                pv.setVisibility(View.GONE);
171            }
172        }
173        if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
174        if (!waiting && mState != STATE_CLOSED) {
175            // it's possible that nothing animated, so we replicate the termination
176            // conditions of panelExpansionChanged here
177            go(STATE_CLOSED);
178            onAllPanelsCollapsed();
179        }
180    }
181
182    public void onPanelPeeked() {
183        if (DEBUG) LOG("onPanelPeeked");
184    }
185
186    public void onAllPanelsCollapsed() {
187        if (DEBUG) LOG("onAllPanelsCollapsed");
188    }
189
190    public void onPanelFullyOpened(PanelView openPanel) {
191        if (DEBUG) LOG("onPanelFullyOpened");
192    }
193
194    public void onTrackingStarted(PanelView panel) {
195        mTracking = true;
196        if (DEBUG && panel != mTouchingPanel) {
197            LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
198                    panel, mTouchingPanel);
199        }
200    }
201
202    public void onTrackingStopped(PanelView panel) {
203        mTracking = false;
204        panelExpansionChanged(panel, panel.getExpandedFraction());
205    }
206}
207