PanelBar.java revision 198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8
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.widget.FrameLayout;
10
11public class PanelBar extends FrameLayout {
12    public static final boolean DEBUG = false;
13    public static final String TAG = PanelBar.class.getSimpleName();
14    public static final void LOG(String fmt, Object... args) {
15        if (!DEBUG) return;
16        Slog.v(TAG, String.format(fmt, args));
17    }
18
19    public static final int STATE_CLOSED = 0;
20    public static final int STATE_OPENING = 1;
21    public static final int STATE_OPEN = 2;
22
23    private PanelHolder mPanelHolder;
24    private ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
25    protected PanelView mTouchingPanel;
26    private int mState = STATE_CLOSED;
27    private boolean mTracking;
28
29    public void go(int state) {
30        LOG("go state: %d -> %d", mState, state);
31        mState = state;
32    }
33
34    public PanelBar(Context context, AttributeSet attrs) {
35        super(context, attrs);
36    }
37
38    @Override
39    protected void onFinishInflate() {
40        super.onFinishInflate();
41    }
42
43    public void addPanel(PanelView pv) {
44        mPanels.add(pv);
45        pv.setBar(this);
46    }
47
48    public void setPanelHolder(PanelHolder ph) {
49        if (ph == null) {
50            Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
51            return;
52        }
53        ph.setBar(this);
54        mPanelHolder = ph;
55        final int N = ph.getChildCount();
56        for (int i=0; i<N; i++) {
57            final PanelView v = (PanelView) ph.getChildAt(i);
58            if (v != null) {
59                addPanel(v);
60            }
61        }
62    }
63
64    public float getBarHeight() {
65        return getMeasuredHeight();
66    }
67
68    public PanelView selectPanelForTouchX(float x) {
69        final int N = mPanels.size();
70        return mPanels.get((int)(N * x / getMeasuredWidth()));
71    }
72
73    public boolean panelsEnabled() {
74        return true;
75    }
76
77    @Override
78    public boolean onTouchEvent(MotionEvent event) {
79        // Allow subclasses to implement enable/disable semantics
80        if (!panelsEnabled()) return false;
81
82        // figure out which panel needs to be talked to here
83        if (event.getAction() == MotionEvent.ACTION_DOWN) {
84            final PanelView panel = selectPanelForTouchX(event.getX());
85            LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s", mState, panel);
86            startOpeningPanel(panel);
87        }
88        final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
89        return result;
90    }
91
92    // called from PanelView when self-expanding, too
93    public void startOpeningPanel(PanelView panel) {
94        LOG("startOpeningPanel: " + panel);
95        mTouchingPanel = panel;
96        mPanelHolder.setSelectedPanel(mTouchingPanel);
97    }
98
99    public void panelExpansionChanged(PanelView panel, float frac) {
100        boolean fullyClosed = true;
101        PanelView fullyOpenedPanel = null;
102        LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
103        for (PanelView pv : mPanels) {
104            // adjust any other panels that may be partially visible
105            if (pv.getExpandedHeight() > 0f) {
106                if (mState == STATE_CLOSED) {
107                    go(STATE_OPENING);
108                    onPanelPeeked();
109                }
110                fullyClosed = false;
111                final float thisFrac = pv.getExpandedFraction();
112                LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
113                if (panel == pv) {
114                    if (thisFrac == 1f) fullyOpenedPanel = panel;
115                } else {
116                    pv.setExpandedFraction(1f-frac);
117                }
118            }
119        }
120        if (fullyOpenedPanel != null && !mTracking) {
121            go(STATE_OPEN);
122            onPanelFullyOpened(fullyOpenedPanel);
123        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
124            go(STATE_CLOSED);
125            onAllPanelsCollapsed();
126        }
127
128        LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
129                (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
130    }
131
132    public void collapseAllPanels(boolean animate) {
133        boolean waiting = false;
134        for (PanelView pv : mPanels) {
135            if (animate && !pv.isFullyCollapsed()) {
136                pv.collapse();
137                waiting = true;
138            } else {
139                pv.setExpandedFraction(0); // just in case
140            }
141        }
142        if (!waiting) {
143            // it's possible that nothing animated, so we replicate the termination
144            // conditions of panelExpansionChanged here
145            go(STATE_CLOSED);
146            onAllPanelsCollapsed();
147        }
148    }
149
150    public void onPanelPeeked() {
151        LOG("onPanelPeeked");
152    }
153
154    public void onAllPanelsCollapsed() {
155        LOG("onAllPanelsCollapsed");
156    }
157
158    public void onPanelFullyOpened(PanelView openPanel) {
159        LOG("onPanelFullyOpened");
160    }
161
162    public void onTrackingStarted(PanelView panel) {
163        mTracking = true;
164        if (panel != mTouchingPanel) {
165            LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
166                    panel, mTouchingPanel);
167        }
168    }
169
170    public void onTrackingStopped(PanelView panel) {
171        mTracking = false;
172        panelExpansionChanged(panel, panel.getExpandedFraction());
173    }
174}
175