131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
197376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Projectimport android.appwidget.AppWidgetHostView;
2031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.LayoutInflater;
2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
2402dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monkimport android.view.ViewConfiguration;
2597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chungimport android.view.ViewGroup;
2606dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohenimport android.widget.RemoteViews;
2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohenimport com.android.launcher3.DragLayer.TouchCompleteListener;
29b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * {@inheritDoc}
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
33b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohenpublic class LauncherAppWidgetHostView extends AppWidgetHostView implements TouchCompleteListener {
34ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
35ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal    LayoutInflater mInflater;
36ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
3788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung    private CheckLongPressHelper mLongPressHelper;
3806dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    private Context mContext;
3906dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    private int mPreviousOrientation;
40b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    private DragLayer mDragLayer;
4199b6a5b5f7808291e26f98ee8064bd9f288c3febMichael Jurka
4202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk    private float mSlop;
4302dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk
447376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project    public LauncherAppWidgetHostView(Context context) {
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context);
4606dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        mContext = context;
4788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung        mLongPressHelper = new CheckLongPressHelper(this);
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
49b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        mDragLayer = ((Launcher) context).getDragLayer();
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
5141d5d6d0768b467f2c7c47ceb027495e4d3f5effAdam Cohen
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected View getErrorView() {
547376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project        return mInflater.inflate(R.layout.appwidget_error, this, false);
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5706dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    @Override
5806dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    public void updateAppWidget(RemoteViews remoteViews) {
5906dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        // Store the orientation in which the widget was inflated
6006dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
6106dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        super.updateAppWidget(remoteViews);
6206dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    }
6306dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen
64ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal    public boolean isReinflateRequired() {
65ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal        // Re-inflate is required if the orientation has changed since last inflated.
6606dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        int orientation = mContext.getResources().getConfiguration().orientation;
6706dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen        if (mPreviousOrientation != orientation) {
6806dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen           return true;
6906dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen       }
7006dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen       return false;
7106dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen    }
7206dff35763bc46884b6464a9bf4406d32cdcaea4Adam Cohen
7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
743798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        // Just in case the previous long press hasn't been cleared, we make sure to start fresh
753798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        // on touch down.
763798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
773798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen            mLongPressHelper.cancelLongPress();
783798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        }
793798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Consume any touch events for ourselves after longpress is triggered
8188f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung        if (mLongPressHelper.hasPerformedLongPress()) {
8288f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung            mLongPressHelper.cancelLongPress();
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return true;
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
8519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Watch for longpress events at this level to make sure
877376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project        // users can always pick up this widget
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (ev.getAction()) {
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_DOWN: {
9088f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung                mLongPressHelper.postCheckForLongPress();
91b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mDragLayer.setTouchCompleteListener(this);
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                break;
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
9419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_UP:
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_CANCEL:
9788f334571fe41df620ba903ced9b2c69b0170d5cWinson Chung                mLongPressHelper.cancelLongPress();
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                break;
9902dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk            case MotionEvent.ACTION_MOVE:
10002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
10102dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                    mLongPressHelper.cancelLongPress();
10202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                }
10302dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                break;
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
10519072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Otherwise continue letting touch events fall through to children
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
109d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
110e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung    public boolean onTouchEvent(MotionEvent ev) {
111e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung        // If the widget does not handle touch, then cancel
112e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung        // long press when we release the touch
113e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung        switch (ev.getAction()) {
114e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung            case MotionEvent.ACTION_UP:
115e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung            case MotionEvent.ACTION_CANCEL:
116e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung                mLongPressHelper.cancelLongPress();
117e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung                break;
11802dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk            case MotionEvent.ACTION_MOVE:
11902dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
12002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                    mLongPressHelper.cancelLongPress();
12102dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                }
12202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk                break;
123e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung        }
124e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung        return false;
125e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung    }
126e7a852ef1511bc18a87168a0821c901e2600da4bWinson Chung
12783f111d129fcb8c50b35da789f0d75604b9c0864Jeff Sharkey    @Override
12802dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk    protected void onAttachedToWindow() {
12902dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk        super.onAttachedToWindow();
13002dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
13102dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk    }
13202dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk
13302dd7aea3d8ac94126a8f8069e6762592ea60326Jason Monk    @Override
13483f111d129fcb8c50b35da789f0d75604b9c0864Jeff Sharkey    public void cancelLongPress() {
13583f111d129fcb8c50b35da789f0d75604b9c0864Jeff Sharkey        super.cancelLongPress();
136b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        mLongPressHelper.cancelLongPress();
137b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
13883f111d129fcb8c50b35da789f0d75604b9c0864Jeff Sharkey
139b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    @Override
140b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public void onTouchComplete() {
1413798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        if (!mLongPressHelper.hasPerformedLongPress()) {
1423798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen            // If a long press has been performed, we don't want to clear the record of that since
1433798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen            // we still may be receiving a touch up which we want to intercept
1443798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen            mLongPressHelper.cancelLongPress();
1453798b643cd8a5c7c85864eced90374cf0fb45640Adam Cohen        }
14683f111d129fcb8c50b35da789f0d75604b9c0864Jeff Sharkey    }
14799b6a5b5f7808291e26f98ee8064bd9f288c3febMichael Jurka
14897d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    @Override
14997d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public int getDescendantFocusability() {
15097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
15197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
153