108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler/*
208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * Copyright (C) 2012 The Android Open Source Project
308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler *
408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * Licensed under the Apache License, Version 2.0 (the "License");
508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * you may not use this file except in compliance with the License.
608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * You may obtain a copy of the License at
708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler *
808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler *      http://www.apache.org/licenses/LICENSE-2.0
908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler *
1008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * Unless required by applicable law or agreed to in writing, software
1108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * distributed under the License is distributed on an "AS IS" BASIS,
1208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * See the License for the specific language governing permissions and
1408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler * limitations under the License.
1508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler */
1608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpackage com.android.systemui.statusbar.phone;
1808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
1908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.content.Context;
204d179dc6ccf3eb118767e94b803484abe9552537Chet Haaseimport android.content.res.Resources;
214d179dc6ccf3eb118767e94b803484abe9552537Chet Haaseimport android.graphics.Canvas;
224d179dc6ccf3eb118767e94b803484abe9552537Chet Haaseimport android.graphics.drawable.Drawable;
2308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.util.AttributeSet;
2464161ccb2f3341ebe1675e38a999250c7967d0adChris Wrenimport android.util.EventLog;
25040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandlerimport android.view.MotionEvent;
2613522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandlerimport android.view.View;
2723b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardtimport android.view.accessibility.AccessibilityEvent;
2813522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler
2964161ccb2f3341ebe1675e38a999250c7967d0adChris Wrenimport com.android.systemui.EventLogTags;
304d179dc6ccf3eb118767e94b803484abe9552537Chet Haaseimport com.android.systemui.R;
31151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandlerimport com.android.systemui.statusbar.GestureRecorder;
3208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
3308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpublic class NotificationPanelView extends PanelView {
3464161ccb2f3341ebe1675e38a999250c7967d0adChris Wren    public static final boolean DEBUG_GESTURES = true;
354d179dc6ccf3eb118767e94b803484abe9552537Chet Haase
364d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    Drawable mHandleBar;
37076324ae191469737afa5bbec577a718f3a31886Daniel Sandler    int mHandleBarHeight;
3813522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler    View mHandleView;
39040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    int mFingers;
40040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    PhoneStatusBar mStatusBar;
412017a056624e747ac91f8203728960a27da0b95aDaniel Sandler    boolean mOkToFlip;
424d179dc6ccf3eb118767e94b803484abe9552537Chet Haase
4308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public NotificationPanelView(Context context, AttributeSet attrs) {
4408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        super(context, attrs);
4513522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler    }
4613522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler
47040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    public void setStatusBar(PhoneStatusBar bar) {
48040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler        mStatusBar = bar;
49040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    }
50040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler
5113522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler    @Override
5213522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler    protected void onFinishInflate() {
5313522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        super.onFinishInflate();
544d179dc6ccf3eb118767e94b803484abe9552537Chet Haase
5513522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        Resources resources = getContext().getResources();
564d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
57076324ae191469737afa5bbec577a718f3a31886Daniel Sandler        mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
5813522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        mHandleView = findViewById(R.id.handle);
5908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
6008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler
6108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    @Override
6208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    public void fling(float vel, boolean always) {
63151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler        GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
64151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler        if (gr != null) {
65151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler            gr.tag(
66151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler                "fling " + ((vel > 0) ? "open" : "closed"),
67151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler                "notifications,v=" + vel);
68151f00d8f06e207038125f227b42f06a25d5e0a0Daniel Sandler        }
6908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler        super.fling(vel, always);
7008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler    }
714d179dc6ccf3eb118767e94b803484abe9552537Chet Haase
7223b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt    @Override
7323b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7423b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
7523b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt            event.getText()
7623b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt                    .add(getContext().getString(R.string.accessibility_desc_notification_shade));
7723b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt            return true;
7823b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt        }
7923b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt
8023b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt        return super.dispatchPopulateAccessibilityEvent(event);
8123b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt    }
8223b0a4e90554cc47f5ec1cef6b15ce0e32bb1ff2Casey Burkhardt
8313522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler    // We draw the handle ourselves so that it's always glued to the bottom of the window.
844d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    @Override
854d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
864d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        super.onLayout(changed, left, top, right, bottom);
874d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        if (changed) {
8813522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler            final int pl = getPaddingLeft();
8913522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler            final int pr = getPaddingRight();
9013522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler            mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
914d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        }
924d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    }
934d179dc6ccf3eb118767e94b803484abe9552537Chet Haase
944d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    @Override
954d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    public void draw(Canvas canvas) {
964d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        super.draw(canvas);
9713522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
9813522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        canvas.translate(0, off);
9913522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        mHandleBar.setState(mHandleView.getDrawableState());
1004d179dc6ccf3eb118767e94b803484abe9552537Chet Haase        mHandleBar.draw(canvas);
10113522a2e40730a0703fd7f185b7fb9be8ae37ab6Daniel Sandler        canvas.translate(0, -off);
1024d179dc6ccf3eb118767e94b803484abe9552537Chet Haase    }
103040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler
104040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    @Override
105040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    public boolean onTouchEvent(MotionEvent event) {
10664161ccb2f3341ebe1675e38a999250c7967d0adChris Wren        if (DEBUG_GESTURES) {
10764161ccb2f3341ebe1675e38a999250c7967d0adChris Wren            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
10864161ccb2f3341ebe1675e38a999250c7967d0adChris Wren                EventLog.writeEvent(EventLogTags.SYSUI_NOTIFICATIONPANEL_TOUCH,
10964161ccb2f3341ebe1675e38a999250c7967d0adChris Wren                       event.getActionMasked(), (int) event.getX(), (int) event.getY());
11064161ccb2f3341ebe1675e38a999250c7967d0adChris Wren            }
11164161ccb2f3341ebe1675e38a999250c7967d0adChris Wren        }
112040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler        if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
113040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler            switch (event.getActionMasked()) {
114040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                case MotionEvent.ACTION_DOWN:
1152017a056624e747ac91f8203728960a27da0b95aDaniel Sandler                    mOkToFlip = getExpandedHeight() == 0;
116040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                    break;
117040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                case MotionEvent.ACTION_POINTER_DOWN:
1182017a056624e747ac91f8203728960a27da0b95aDaniel Sandler                    if (mOkToFlip) {
119040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        float miny = event.getY(0);
120040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        float maxy = miny;
121040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        for (int i=1; i<event.getPointerCount(); i++) {
122040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            final float y = event.getY(i);
123040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            if (y < miny) miny = y;
124040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            if (y > maxy) maxy = y;
125040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        }
126040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        if (maxy - miny < mHandleBarHeight) {
127040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            if (getMeasuredHeight() < mHandleBarHeight) {
128040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                                mStatusBar.switchToSettings();
129040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            } else {
130040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                                mStatusBar.flipToSettings();
131040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                            }
1322017a056624e747ac91f8203728960a27da0b95aDaniel Sandler                            mOkToFlip = false;
133040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                        }
134040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                    }
135040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler                    break;
136040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler            }
137040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler        }
138040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler        return mHandleView.dispatchTouchEvent(event);
139040c2e4ace25a45bc701821da4fa786e6dd75eadDaniel Sandler    }
14008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler}
141