1/*
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
17package com.android.systemui.statusbar.phone;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.util.Log;
22import android.view.MotionEvent;
23import android.view.View;
24import android.widget.FrameLayout;
25
26public abstract class PanelBar extends FrameLayout {
27    public static final boolean DEBUG = false;
28    public static final String TAG = PanelBar.class.getSimpleName();
29    private static final boolean SPEW = false;
30
31    public static final void LOG(String fmt, Object... args) {
32        if (!DEBUG) return;
33        Log.v(TAG, String.format(fmt, args));
34    }
35
36    public static final int STATE_CLOSED = 0;
37    public static final int STATE_OPENING = 1;
38    public static final int STATE_OPEN = 2;
39
40    PanelView mPanel;
41    private int mState = STATE_CLOSED;
42    private boolean mTracking;
43
44    public void go(int state) {
45        if (DEBUG) LOG("go state: %d -> %d", mState, state);
46        mState = state;
47    }
48
49    public int getState() {
50        return mState;
51    }
52
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 setPanel(PanelView pv) {
63        mPanel = pv;
64        pv.setBar(this);
65    }
66
67    public void setBouncerShowing(boolean showing) {
68        int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
69                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
70
71        setImportantForAccessibility(important);
72
73        if (mPanel != null) mPanel.setImportantForAccessibility(important);
74    }
75
76    public boolean panelEnabled() {
77        return true;
78    }
79
80    @Override
81    public boolean onTouchEvent(MotionEvent event) {
82        // Allow subclasses to implement enable/disable semantics
83        if (!panelEnabled()) {
84            if (event.getAction() == MotionEvent.ACTION_DOWN) {
85                Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
86                        (int) event.getX(), (int) event.getY()));
87            }
88            return false;
89        }
90
91        if (event.getAction() == MotionEvent.ACTION_DOWN) {
92            final PanelView panel = mPanel;
93            if (panel == null) {
94                // panel is not there, so we'll eat the gesture
95                Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
96                        (int) event.getX(), (int) event.getY()));
97                return true;
98            }
99            boolean enabled = panel.isEnabled();
100            if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,
101                    (enabled ? "" : " (disabled)"));
102            if (!enabled) {
103                // panel is disabled, so we'll eat the gesture
104                Log.v(TAG, String.format(
105                        "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
106                        panel, (int) event.getX(), (int) event.getY()));
107                return true;
108            }
109        }
110        return mPanel == null || mPanel.onTouchEvent(event);
111    }
112
113    public abstract void panelScrimMinFractionChanged(float minFraction);
114
115    /**
116     * @param frac the fraction from the expansion in [0, 1]
117     * @param expanded whether the panel is currently expanded; this is independent from the
118     *                 fraction as the panel also might be expanded if the fraction is 0
119     */
120    public void panelExpansionChanged(float frac, boolean expanded) {
121        boolean fullyClosed = true;
122        boolean fullyOpened = false;
123        if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
124        PanelView pv = mPanel;
125        pv.setVisibility(expanded ? VISIBLE : INVISIBLE);
126        // adjust any other panels that may be partially visible
127        if (expanded) {
128            if (mState == STATE_CLOSED) {
129                go(STATE_OPENING);
130                onPanelPeeked();
131            }
132            fullyClosed = false;
133            final float thisFrac = pv.getExpandedFraction();
134            if (SPEW) LOG("panelExpansionChanged:  -> %s: f=%.1f", pv.getName(), thisFrac);
135            fullyOpened = thisFrac >= 1f;
136        }
137        if (fullyOpened && !mTracking) {
138            go(STATE_OPEN);
139            onPanelFullyOpened();
140        } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
141            go(STATE_CLOSED);
142            onPanelCollapsed();
143        }
144
145        if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
146                fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
147    }
148
149    public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
150        boolean waiting = false;
151        PanelView pv = mPanel;
152        if (animate && !pv.isFullyCollapsed()) {
153            pv.collapse(delayed, speedUpFactor);
154            waiting = true;
155        } else {
156            pv.resetViews();
157            pv.setExpandedFraction(0); // just in case
158            pv.cancelPeek();
159        }
160        if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
161        if (!waiting && mState != STATE_CLOSED) {
162            // it's possible that nothing animated, so we replicate the termination
163            // conditions of panelExpansionChanged here
164            go(STATE_CLOSED);
165            onPanelCollapsed();
166        }
167    }
168
169    public void onPanelPeeked() {
170        if (DEBUG) LOG("onPanelPeeked");
171    }
172
173    public boolean isClosed() {
174        return mState == STATE_CLOSED;
175    }
176
177    public void onPanelCollapsed() {
178        if (DEBUG) LOG("onPanelCollapsed");
179    }
180
181    public void onPanelFullyOpened() {
182        if (DEBUG) LOG("onPanelFullyOpened");
183    }
184
185    public void onTrackingStarted() {
186        mTracking = true;
187    }
188
189    public void onTrackingStopped(boolean expand) {
190        mTracking = false;
191    }
192
193    public void onExpandingFinished() {
194        if (DEBUG) LOG("onExpandingFinished");
195    }
196
197    public void onClosingFinished() {
198
199    }
200}
201