PanelBar.java revision c38bbc391ae4ec5945d5fa408da3994552f775eb
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 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
71    public PanelView selectPanelForTouchX(float x) {
72        final int N = mPanels.size();
73        return mPanels.get((int)(N * x / 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 = selectPanelForTouchX(event.getX());
88            boolean enabled = panel.isEnabled();
89            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
90                    (enabled ? "" : " (disabled)"));
91            if (!enabled)
92                return false;
93            startOpeningPanel(panel);
94        }
95        final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
96        return result;
97    }
98
99    // called from PanelView when self-expanding, too
100    public void startOpeningPanel(PanelView panel) {
101        if (DEBUG) LOG("startOpeningPanel: " + panel);
102        mTouchingPanel = panel;
103        mPanelHolder.setSelectedPanel(mTouchingPanel);
104        for (PanelView pv : mPanels) {
105            if (pv != panel) {
106                pv.collapse();
107            }
108        }
109    }
110
111    public void panelExpansionChanged(PanelView panel, float frac) {
112        boolean fullyClosed = true;
113        PanelView fullyOpenedPanel = null;
114        if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
115        mPanelExpandedFractionSum = 0f;
116        for (PanelView pv : mPanels) {
117            final boolean visible = pv.getVisibility() == View.VISIBLE;
118            // adjust any other panels that may be partially visible
119            if (pv.getExpandedHeight() > 0f) {
120                if (mState == STATE_CLOSED) {
121                    go(STATE_OPENING);
122                    onPanelPeeked();
123                }
124                fullyClosed = false;
125                final float thisFrac = pv.getExpandedFraction();
126                mPanelExpandedFractionSum += (visible ? thisFrac : 0);
127                if (DEBUG) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
128                if (panel == pv) {
129                    if (thisFrac == 1f) fullyOpenedPanel = panel;
130                }
131            }
132            if (pv.getExpandedHeight() > 0f) {
133                if (!visible) pv.setVisibility(View.VISIBLE);
134            } else {
135                if (visible) pv.setVisibility(View.GONE);
136            }
137        }
138        mPanelExpandedFractionSum /= mPanels.size();
139        if (fullyOpenedPanel != null && !mTracking) {
140            go(STATE_OPEN);
141            onPanelFullyOpened(fullyOpenedPanel);
142        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
143            go(STATE_CLOSED);
144            onAllPanelsCollapsed();
145        }
146
147        if (DEBUG) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
148                (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
149    }
150
151    public void collapseAllPanels(boolean animate) {
152        boolean waiting = false;
153        for (PanelView pv : mPanels) {
154            if (animate && !pv.isFullyCollapsed()) {
155                pv.collapse();
156                waiting = true;
157            } else {
158                pv.setExpandedFraction(0); // just in case
159                pv.setVisibility(View.GONE);
160            }
161        }
162        if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
163        if (!waiting && mState != STATE_CLOSED) {
164            // it's possible that nothing animated, so we replicate the termination
165            // conditions of panelExpansionChanged here
166            go(STATE_CLOSED);
167            onAllPanelsCollapsed();
168        }
169    }
170
171    public void onPanelPeeked() {
172        if (DEBUG) LOG("onPanelPeeked");
173    }
174
175    public void onAllPanelsCollapsed() {
176        if (DEBUG) LOG("onAllPanelsCollapsed");
177    }
178
179    public void onPanelFullyOpened(PanelView openPanel) {
180        if (DEBUG) LOG("onPanelFullyOpened");
181    }
182
183    public void onTrackingStarted(PanelView panel) {
184        mTracking = true;
185        if (DEBUG && panel != mTouchingPanel) {
186            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    }
195}
196