DragLayer.java revision 47328fd53f43fd0c2ed14ad925dd04483f9229a0
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 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
17fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevpackage com.android.launcher3.dragndrop;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator;
20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter;
21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator;
22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator;
23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources;
26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas;
270fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyalimport android.graphics.Color;
286788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
2995cdb3a0211650e76adb451588ce89fd585b178fTony Wickhamimport android.graphics.Region;
30360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.drawable.Drawable;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
32d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshevimport android.view.DragEvent;
3326279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.KeyEvent;
3426279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.MotionEvent;
3526279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.View;
3626279c6d0917015eb4e6de0743b79edeea25f9bcDave Hawkeyimport android.view.ViewGroup;
373371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
383371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
39716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
403e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
42ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.AppWidgetResizeFrame;
45645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.BaseContainerView;
46fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.CellLayout;
47fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.InsettableFrameLayout;
48fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.ItemInfo;
49fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Launcher;
50fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAppState;
51fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.LauncherAppWidgetHostView;
52dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickhamimport com.android.launcher3.PinchToOverviewListener;
53f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohenimport com.android.launcher3.R;
5447328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyalimport com.android.launcher3.DropTargetBar;
55fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.ShortcutAndWidgetContainer;
56fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Utilities;
57fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834Vadim Tryshevimport com.android.launcher3.Workspace;
5883a8f042adda926489494dff217c15ab696139b4Sunny Goyalimport com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
59645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsContainerView;
60645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.allapps.AllAppsTransitionController;
619c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickhamimport com.android.launcher3.config.FeatureFlags;
62261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.Folder;
63261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.FolderIcon;
64091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
65645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Songimport com.android.launcher3.util.TouchController;
66bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
671d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
686788269814a678af976dfc7d6135993e172ce586Adam Cohen
6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
700e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
72a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohenpublic class DragLayer extends InsettableFrameLayout {
730fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal
74b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_DISAPPEAR = 0;
75b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
76b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
770fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal    // Scrim color without any alpha component.
780fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal    private static final int SCRIM_COLOR = Color.BLACK & 0x00FFFFFF;
790fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal
80b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final int[] mTmpXY = new int[2];
81b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal
82091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragController mDragController;
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
84716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private int mXDown, mYDown;
85716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
86716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
876788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
88b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final ArrayList<AppWidgetResizeFrame> mResizeFrames = new ArrayList<>();
897066003b2032a49ae5e59dab9b706259bdeb7e6eSunny Goyal    private final boolean mIsRtl;
906788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
91716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
92716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
93716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
94b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
95091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DragView mDropView = null;
96091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk int mAnchorViewInitialScrollX = 0;
97091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk View mAnchorView = null;
988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
100b135956e95d2d7479290af89d618892ed0e7327dSunny Goyal    private final Rect mHitRect = new Rect();
10195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    private final Rect mHighlightRect = new Rect();
1026788269814a678af976dfc7d6135993e172ce586Adam Cohen
103b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    private TouchCompleteListener mTouchCompleteListener;
104b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
105432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    private View mOverlayView;
106432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    private int mTopViewIndex;
1072d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen    private int mChildCountOnLastUpdate = -1;
10855bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi
1096c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    // Darkening scrim
1106c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    private float mBackgroundAlpha = 0;
1116c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
1120f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    // Related to adjacent page hints
1130f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private final Rect mScrollChildPosition = new Rect();
1140f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private boolean mInScrollArea;
1150f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private boolean mShowPageHints;
1160f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private Drawable mLeftHoverDrawable;
1170f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private Drawable mRightHoverDrawable;
1180f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private Drawable mLeftHoverDrawableActive;
1190f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private Drawable mRightHoverDrawableActive;
1200f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
121dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham    // Related to pinch-to-go-to-overview gesture.
1229c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickham    private PinchToOverviewListener mPinchListener = null;
123645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
124645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    // Handles all apps pull up interaction
125645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private AllAppsTransitionController mAllAppsController;
126645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
127645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    private TouchController mActiveController;
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1320e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
136be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
137be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
138be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
13921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
140360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
1410f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        final Resources res = getResources();
1420f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mLeftHoverDrawable = res.getDrawable(R.drawable.page_hover_left);
1430f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mRightHoverDrawable = res.getDrawable(R.drawable.page_hover_right);
1440f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mLeftHoverDrawableActive = res.getDrawable(R.drawable.page_hover_left_active);
1450f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mRightHoverDrawableActive = res.getDrawable(R.drawable.page_hover_right_active);
1460f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mIsRtl = Utilities.isRtl(res);
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
149645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song    public void setup(Launcher launcher, DragController dragController,
150645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            AllAppsTransitionController allAppsTransitionController) {
1514c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
152645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mDragController = dragController;
153645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        mAllAppsController = allAppsTransitionController;
154dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham
155e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        boolean isAccessibilityEnabled = ((AccessibilityManager) mLauncher.getSystemService(
156e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                Context.ACCESSIBILITY_SERVICE)).isEnabled();
157e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        onAccessibilityStateChanged(isAccessibilityEnabled);
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
15976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
16200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
165e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    public void onAccessibilityStateChanged(boolean isAccessibilityEnabled) {
166e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham        mPinchListener = FeatureFlags.LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW || isAccessibilityEnabled
167e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham                ? null : new PinchToOverviewListener(mLauncher);
168e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham    }
169e22172537b9235a5ba41b3054677dd7ed6d89f02Tony Wickham
170b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen    public void showOverlayView(View overlayView) {
171432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
172b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        mOverlayView = overlayView;
173b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        addView(overlayView, lp);
174b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen
175b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        // ensure that the overlay view stays on top. we can't use drawing order for this
176b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        // because in API level 16 touch dispatch doesn't respect drawing order.
177b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        mOverlayView.bringToFront();
178432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    }
179432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen
180432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    public void dismissOverlayView() {
181432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        removeView(mOverlayView);
182432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    }
183432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen
1843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
1853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
18647328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        return mHitRect.contains((int) ev.getX(), (int) ev.getY());
1873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1883371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
1893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder, mHitRect);
19147328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        return mHitRect.contains((int) ev.getX(), (int) ev.getY());
1923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
194ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isEventOverDropTargetBar(MotionEvent ev) {
19547328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        getDescendantRectRelativeToSelf(mLauncher.getDropTargetBar(), mHitRect);
19647328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal        return mHitRect.contains((int) ev.getX(), (int) ev.getY());
197ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
198ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
19976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
2006788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
2016788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
2026788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
2036788269814a678af976dfc7d6135993e172ce586Adam Cohen
2046788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
2056788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
2066788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
2076788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
2086788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
2096788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
2106788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
2116788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
2126788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
2136788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2146788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2156788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
21676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
2171d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
218424418bb50ccf5d9270650b70cc51f423da51a65Sunny Goyal        if (currentFolder != null && intercept) {
2191d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            if (currentFolder.isEditingName()) {
2203371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
2211d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen                    currentFolder.dismissEditingName();
22276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                    return true;
2232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
2242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
22576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
2263371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (!isEventOverFolder(currentFolder, ev)) {
227ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                if (isInAccessibleDrag()) {
228ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                    // Do not close the folder if in drag and drop.
229ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                    if (!isEventOverDropTargetBar(ev)) {
230ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        return true;
231ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                    }
232ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                } else {
233ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                    mLauncher.closeFolder();
234ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                    return true;
235ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                }
23676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
2372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
2386788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
2396788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2406788269814a678af976dfc7d6135993e172ce586Adam Cohen
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
243b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        int action = ev.getAction();
244b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
245645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
246b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
24776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
2486788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
249d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
250b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
251b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
252b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
253b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
254b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
2551b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
2566788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
257dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham
258645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (mDragController.onInterceptTouchEvent(ev)) {
259645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mDragController;
260645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
261645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
262645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (mAllAppsController.onInterceptTouchEvent(ev)) {
263645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mAllAppsController;
264645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return true;
265645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
266645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song
2679c43182ff1d095b1bbaacedefe6e0f4c2deb17e3Tony Wickham        if (mPinchListener != null && mPinchListener.onInterceptTouchEvent(ev)) {
268c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            // Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
269645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            mActiveController = mPinchListener;
270c5b31965d9bcb4c9899e2d1c45b5c95c70bac9f2Tony Wickham            return true;
271dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham        }
272645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
2763371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
277023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        if (mLauncher == null || mLauncher.getWorkspace() == null) {
278023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka            return false;
279023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        }
2803371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
2813371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
2823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
2833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
2848b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
2858b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2868b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
2873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
288ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                boolean isOverFolderOrSearchBar;
2893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
2903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
291ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
292ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
293ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar) {
2943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
298693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
299693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        break;
3003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
301ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        isOverFolderOrSearchBar = isEventOverFolder(currentFolder, ev) ||
302ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                            (isInAccessibleDrag() && isEventOverDropTargetBar(ev));
303ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        if (!isOverFolderOrSearchBar && !mHoverPointClosesFolder) {
3043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
3053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
3063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
307ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                        } else if (!isOverFolderOrSearchBar) {
3083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
3093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
310693fbc7f1737d89f11f9ab81558c109f0883ab0eMihail Dumitrescu                        mHoverPointClosesFolder = false;
3113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
3123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
3133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
3143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
3153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
3188b805b17158886035b38261eb611d8641701ae43Michael Jurka        AccessibilityManager accessibilityManager = (AccessibilityManager)
3198b805b17158886035b38261eb611d8641701ae43Michael Jurka                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
3208b805b17158886035b38261eb611d8641701ae43Michael Jurka        if (accessibilityManager.isEnabled()) {
3213371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
3223371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityEvent event = AccessibilityEvent.obtain(
3233371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
3243371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            onInitializeAccessibilityEvent(event);
3258b805b17158886035b38261eb611d8641701ae43Michael Jurka            event.getText().add(getContext().getString(stringId));
3268b805b17158886035b38261eb611d8641701ae43Michael Jurka            accessibilityManager.sendAccessibilityEvent(event);
3273371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
32883ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
32983ca480941b3dd635b62347008fc8d7859d82002Winson Chung
330ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    private boolean isInAccessibleDrag() {
331ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal        LauncherAccessibilityDelegate delegate = LauncherAppState
332ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                .getInstance().getAccessibilityDelegate();
333ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal        return delegate != null && delegate.isInAccessibleDrag();
334ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal    }
335ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
33683ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
33783ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
33883ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
33983ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
34083ca480941b3dd635b62347008fc8d7859d82002Winson Chung            if (child == currentFolder) {
34183ca480941b3dd635b62347008fc8d7859d82002Winson Chung                return super.onRequestSendAccessibilityEvent(child, event);
34283ca480941b3dd635b62347008fc8d7859d82002Winson Chung            }
343ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
34447328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal            if (isInAccessibleDrag() && child instanceof DropTargetBar) {
345ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal                return super.onRequestSendAccessibilityEvent(child, event);
346ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            }
34783ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Skip propagating onRequestSendAccessibilityEvent all for other children
34883ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // when a folder is open
34983ca480941b3dd635b62347008fc8d7859d82002Winson Chung            return false;
35083ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
35183ca480941b3dd635b62347008fc8d7859d82002Winson Chung        return super.onRequestSendAccessibilityEvent(child, event);
35283ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
35383ca480941b3dd635b62347008fc8d7859d82002Winson Chung
35483ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
35583ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
35683ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
35783ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
35883ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Only add the folder as a child for accessibility when it is open
35983ca480941b3dd635b62347008fc8d7859d82002Winson Chung            childrenForAccessibility.add(currentFolder);
360ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal
361ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            if (isInAccessibleDrag()) {
36247328fd53f43fd0c2ed14ad925dd04483f9229a0Sunny Goyal                childrenForAccessibility.add(mLauncher.getDropTargetBar());
363ccc414bb1e18206d2a3d8d797070278bdb286354Sunny Goyal            }
36483ca480941b3dd635b62347008fc8d7859d82002Winson Chung        } else {
36583ca480941b3dd635b62347008fc8d7859d82002Winson Chung            super.addChildrenForAccessibility(childrenForAccessibility);
36683ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
3673371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3693371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
3703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
3713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
3723371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
3733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
3743371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
3753371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
3763371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
3786788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
3796788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
3806788269814a678af976dfc7d6135993e172ce586Adam Cohen
3816788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
3826788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
3836788269814a678af976dfc7d6135993e172ce586Adam Cohen
384dadb304b4682998c43b9c07bef45b9a9380f3287Tony Wickham
385b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        if (action == MotionEvent.ACTION_DOWN) {
386b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (handleTouchDown(ev, false)) {
387b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                return true;
388b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            }
389b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
390b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            if (mTouchCompleteListener != null) {
391b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen                mTouchCompleteListener.onTouchComplete();
3926788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
393b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen            mTouchCompleteListener = null;
3946788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3956788269814a678af976dfc7d6135993e172ce586Adam Cohen
3966788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
3976788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
3986788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
3996788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
4006788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
4016788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
4026788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
4036788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
404bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
405bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.onTouchUp();
4066788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
4076788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
4086788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4096788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
410645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        if (mActiveController != null) {
411645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song            return mActiveController.onTouchEvent(ev);
412645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        }
413645764e3e5fa34d9adcddfc722d726b76f048306Hyunyoung Song        return false;
41491a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
415ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
416d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    @Override
417d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    public boolean onDragEvent (DragEvent event) {
418d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        return mDragController.onDragEvent(event);
419d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev    }
420d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev
42135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
42235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
42335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
42435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
42535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
42635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
42735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
428ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
429716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
430716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
431ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
4327d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
4338dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
4347d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[0] + scale * descendant.getMeasuredWidth()),
4357d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen                (int) (mTmpXY[1] + scale * descendant.getMeasuredHeight()));
436ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
437716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
43876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
439307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen    public float getLocationInDragLayer(View child, int[] loc) {
44035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
44135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
442307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        return getDescendantCoordRelativeToSelf(child, loc);
44335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
44435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
4457d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
4467d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen        return getDescendantCoordRelativeToSelf(descendant, coord, false);
4477d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    }
4487d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen
44935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
45035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
45135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
45235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
45335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
45435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
4557d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * @param includeRootScroll Whether or not to account for the scroll of the root descendant:
4567d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     *          sometimes this is relevant as in a child's coordinates within the root descendant.
457307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
458307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
459307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         assumption fails, we will need to return a pair of scale factors.
46035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
4617d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
4627d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen            boolean includeRootScroll) {
463c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung        return Utilities.getDescendantCoordRelativeToParent(descendant, this,
464c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung                coord, includeRootScroll);
465c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung    }
466c9ca2980983ab21fc8631c7a65399d6d9c70f39cWinson Chung
4677d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    /**
4687d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
4697d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen     */
4707d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen    public float mapCoordInSelfToDescendent(View descendant, int[] coord) {
471c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung        return Utilities.mapCoordInSelfToDescendent(descendant, this, coord);
47276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
47376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
4743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
4753e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
4768dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
4773e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
4783e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
479716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4808dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
4813e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
4823e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
483716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4843e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
4853e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
4863e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
487716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
488716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
489ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
490ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
491ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
492ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
493120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
494bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
495bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public LayoutParams generateLayoutParams(AttributeSet attrs) {
496bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(getContext(), attrs);
497bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
498bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
499bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
500bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateDefaultLayoutParams() {
501bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
502bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
503bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
504bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    // Override to allow type-checking of LayoutParams.
505bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
506bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
507bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return p instanceof LayoutParams;
508bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
509bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
510bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    @Override
511bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
512bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        return new LayoutParams(p);
513bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    }
514bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
515bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen    public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
5166788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
5176788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
5186788269814a678af976dfc7d6135993e172ce586Adam Cohen
519bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(Context c, AttributeSet attrs) {
520bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(c, attrs);
521bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
522bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
5236788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
5246788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
5256788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5266788269814a678af976dfc7d6135993e172ce586Adam Cohen
527bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        public LayoutParams(ViewGroup.LayoutParams lp) {
528bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen            super(lp);
529bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen        }
530bc927f9c24001e250622ca9a2547ee5b65baef58Adam Cohen
5316788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
5326788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
5336788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5346788269814a678af976dfc7d6135993e172ce586Adam Cohen
5356788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
5366788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
5376788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5386788269814a678af976dfc7d6135993e172ce586Adam Cohen
5396788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
5406788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
5416788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5426788269814a678af976dfc7d6135993e172ce586Adam Cohen
5436788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
5446788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
5456788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5466788269814a678af976dfc7d6135993e172ce586Adam Cohen
5476788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
5486788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
5496788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5506788269814a678af976dfc7d6135993e172ce586Adam Cohen
5516788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
5526788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
5536788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5546788269814a678af976dfc7d6135993e172ce586Adam Cohen
5556788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
5566788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
5576788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5586788269814a678af976dfc7d6135993e172ce586Adam Cohen
5596788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
5606788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
5616788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5626788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5636788269814a678af976dfc7d6135993e172ce586Adam Cohen
5646788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
5656788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
5666788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
5676788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
5686788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
5696788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
5706788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
5716788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
5726788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
5736788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
5746788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
5756788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
5766788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5776788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5786788269814a678af976dfc7d6135993e172ce586Adam Cohen
5796788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
5806788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
5816788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
582bebf042666cffe52039b875a549a582abd78a431Adam Cohen                frame.commitResize();
5836788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
5846788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
5856788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
5866788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
5876788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5886788269814a678af976dfc7d6135993e172ce586Adam Cohen
5896788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
5906788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
5916788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5926788269814a678af976dfc7d6135993e172ce586Adam Cohen
5936788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
5946788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
5956788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
5966788269814a678af976dfc7d6135993e172ce586Adam Cohen
5976788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
5986788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
5996788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
6003a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka                widget, cellLayout, this);
6016788269814a678af976dfc7d6135993e172ce586Adam Cohen
6026788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
6036788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
6046788269814a678af976dfc7d6135993e172ce586Adam Cohen
6056788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
6066788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
6076788269814a678af976dfc7d6135993e172ce586Adam Cohen
6086788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
6096788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
610716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
6117bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
6127bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
6137bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
614b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
615b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
616b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
617b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
618b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
6197bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
620ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
621ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
622ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
623557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
62428f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
62528f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView);
626ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
627ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
628ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
6296441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
630a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
631716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
632eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
633716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
6343e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
6353e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
636716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
637716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
638307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        float childScale = child.getScaleX();
639307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
640307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
641eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
6428dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
643ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
644557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
645307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // We need to account for the scale of the child itself, as the above only accounts for
646307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // for the scale in parents.
647307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        scale *= childScale;
648ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
649ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
650eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        float toScale = scale;
6514497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        if (child instanceof TextView) {
6524497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            TextView tv = (TextView) child;
653eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // Account for the source scale of the icon (ie. from AllApps to Workspace, in which
654eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            // the workspace may have smaller icon bounds).
655eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toScale = scale / dragView.getIntrinsicIconScaleFactor();
6564497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn
6574497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // The child may be scaled (always about the center of the view) so to account for it,
6584497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // we have to offset the position by the scaled size.  Once we do that, we can center
6594497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // the drag view about the scaled child view.
660eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY += Math.round(toScale * tv.getPaddingTop());
661eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung            toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2;
66295abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            if (dragView.getDragVisualizeOffset() != null) {
66395abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal                toY -=  Math.round(toScale * dragView.getDragVisualizeOffset().y);
66495abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal            }
66595abbb330ce9bbaf23594245f0f8a795c8118038Sunny Goyal
6664497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
6674497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        } else if (child instanceof FolderIcon) {
668ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
6695f8afe6280eae34620067696173e71943e1a30a3Winson Chung            toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop()));
670307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
671307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
672ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
673ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
674ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
675ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
676ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
677ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
678ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
679716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
680ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
681ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
682716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
6838dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
6848dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
6858dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
686d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
687d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
688d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
6898dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
6908dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
691eeb5bbc9409978cc2ae52d48380399fcde3d9f85Winson Chung        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale,
692d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
693557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
694557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
695d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
696ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
697ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
698ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
6998dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
7008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
7013e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
702ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
703ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
7043e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
7053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
706b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
707b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
708b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
709b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
710b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
711b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
712b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
713b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
714b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
715b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
716b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalScale The final scale of the view. The view is scaled about its center.
717b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
718b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
719b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
720b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
721b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
722b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        the runnable will execute after the view is faded out.
7236441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
7246441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
7256441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
726b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
7277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
7287bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
7297bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
7307bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
7317bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
7327bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
733716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
734f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        final float dist = (float) Math.hypot(to.left - from.left, to.top - from.top);
735716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
736716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
7373e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
7383e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
7393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
7403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
7413e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (dist < maxDist) {
7428dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
7433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
74461b0c69d3fe331d3de338322396d5de691d58613Winson Chung            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
745716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
746716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
747043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
748043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
7493e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
750043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
7513e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
752716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
753043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
7547bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
755043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
756043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
757043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
758716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
759716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
7607bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
7617bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
762716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
7633e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
7643e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
7653e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
7663e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
767a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
7687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
7697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
7707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
7717bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
7727bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
7737bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7747bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
7757bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
7767bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7777bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
7787bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
7797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
78028f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() *
78128f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                    (mAnchorViewInitialScrollX - mAnchorView.getScrollX()));
78228f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen
78328f852ab678d9750879b6d3549bf5da176cf1225Adam Cohen                int xPos = x - mDropView.getScrollX() + anchorAdjust;
7847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
7857bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7867bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
7877bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
7887bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
7897bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
7907bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
791716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
792043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
793043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
794043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
795043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
796043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
797043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
798043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
799043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
800043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
801043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
802043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
803043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
804043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
805043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
806d6c8e7eeb13094ea1349897663ae28d8a3bf2773Vadim Tryshev        mDropView.requestLayout();
807043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
808043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
809043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
810043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
811043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
812043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
813043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
814043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
815043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
816043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
817043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
818043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
819043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
8203e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
8213e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
8228dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
8238dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
8248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
825ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
826ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
827ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
828ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
829ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
830ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
8313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
8323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
8333e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
834716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
835716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
836716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
837ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
8387bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
8397bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
8407bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
8417bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
8422d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            mDragController.onDeferredEndDrag(mDropView);
8437bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
844ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
845ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
846ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
847ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
848ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
849ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
850ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
851ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
852716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
8538b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
854a6d0492e5f0dd4e1b43d4034a770241dc65f8f8cAdam Cohen        super.onChildViewAdded(parent, child);
855b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        if (mOverlayView != null) {
856b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            // ensure that the overlay view stays on top. we can't use drawing order for this
857b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            // because in API level 16 touch dispatch doesn't respect drawing order.
858b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            mOverlayView.bringToFront();
859b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        }
86021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
86121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
86221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
86321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
8648b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
86521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
86621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
86721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
868432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    @Override
869432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    public void bringChildToFront(View child) {
870432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        super.bringChildToFront(child);
871b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        if (child != mOverlayView && mOverlayView != null) {
872b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            // ensure that the overlay view stays on top. we can't use drawing order for this
873b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            // because in API level 16 touch dispatch doesn't respect drawing order.
874b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            mOverlayView.bringToFront();
875b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen        }
876432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        updateChildIndices();
877432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen    }
878432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen
87921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
880432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        mTopViewIndex = -1;
88155bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        int childCount = getChildCount();
88255bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        for (int i = 0; i < childCount; i++) {
883b670f195ffb7b4a0519fd0b337b68f7412159414Adam Cohen            if (getChildAt(i) instanceof DragView) {
884432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen                mTopViewIndex = i;
88555bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi            }
88621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
8872d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        mChildCountOnLastUpdate = childCount;
88821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
88921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
89021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
89121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
8922d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        if (mChildCountOnLastUpdate != childCount) {
8932d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // between platform versions 17 and 18, behavior for onChildViewRemoved / Added changed.
8942d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // Pre-18, the child was not added / removed by the time of those callbacks. We need to
8952d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // force update our representation of things here to avoid crashing on pre-18 devices
8962d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            // in certain instances.
8972d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen            updateChildIndices();
8982d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen        }
8992d783ce2f4b2e507bead0d723f0edcdf902dbd46Adam Cohen
900432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        // i represents the current draw iteration
901432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        if (mTopViewIndex == -1) {
902432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // in general we do nothing
90321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
904432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i == childCount - 1) {
905432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // if we have a top index, we return it when drawing last item (highest z-order)
906432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return mTopViewIndex;
907432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen        } else if (i < mTopViewIndex) {
90821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
90955bd9725d5c0373b89f7b9bbd9547550ea3bbc63Jorim Jaggi        } else {
910432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // for indexes greater than the top index, we fetch one item above to shift for the
911432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            // displacement of the top index
912432609a246819f3cf887a80c2ae56b61fc5ca25aAdam Cohen            return i + 1;
91321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
91421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
915360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
916e0c332365604976d999eb25d4bdcc49ec75b7a1cTony Wickham    void onEnterScrollArea() {
9170f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mInScrollArea = true;
9180f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        invalidate();
9190f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
9200f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9210f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    void onExitScrollArea() {
9220f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mInScrollArea = false;
9230f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        invalidate();
9240f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
9250f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9260f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    public void showPageHints() {
9270f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mShowPageHints = true;
9280f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        Workspace workspace = mLauncher.getWorkspace();
9290f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.numCustomPages()),
9300f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                mScrollChildPosition);
9310f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        invalidate();
9320f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
9330f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9340f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    public void hidePageHints() {
9350f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        mShowPageHints = false;
9360f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        invalidate();
9370f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
9380f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
93995cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    public void invalidateScrim() {
94095cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        if (mBackgroundAlpha > 0.0f) {
94195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            invalidate();
94295cdb3a0211650e76adb451588ce89fd585b178fTony Wickham        }
94395cdb3a0211650e76adb451588ce89fd585b178fTony Wickham    }
94495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
945360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    @Override
946360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    protected void dispatchDraw(Canvas canvas) {
9470fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        // Draw the background below children.
9480fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal        if (mBackgroundAlpha > 0.0f) {
94995cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            // Update the scroll position first to ensure scrim cutout is in the right place.
95095cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            mLauncher.getWorkspace().computeScrollWithoutInvalidation();
95195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham
9526c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            int alpha = (int) (mBackgroundAlpha * 255);
95395cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            CellLayout currCellLayout = mLauncher.getWorkspace().getCurrentDragOverlappingLayout();
95495cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.save();
95595cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            if (currCellLayout != null && currCellLayout != mLauncher.getHotseat().getLayout()) {
95695cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                // Cut a hole in the darkening scrim on the page that should be highlighted, if any.
95795cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                getDescendantRectRelativeToSelf(currCellLayout, mHighlightRect);
95895cdb3a0211650e76adb451588ce89fd585b178fTony Wickham                canvas.clipRect(mHighlightRect, Region.Op.DIFFERENCE);
95995cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            }
9600fa93bc5c65a2d7d5e5f4e798499903759c48cc5Sunny Goyal            canvas.drawColor((alpha << 24) | SCRIM_COLOR);
96195cdb3a0211650e76adb451588ce89fd585b178fTony Wickham            canvas.restore();
9626c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
9636c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
964360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        super.dispatchDraw(canvas);
9658cc05507150fea5282b7581e1a268967a702bcc9Adam Cohen    }
966360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
9670f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    private void drawPageHints(Canvas canvas) {
9680f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        if (mShowPageHints) {
9690f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            Workspace workspace = mLauncher.getWorkspace();
9700f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            int width = getMeasuredWidth();
9710f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            int page = workspace.getNextPage();
9720f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            CellLayout leftPage = (CellLayout) workspace.getChildAt(mIsRtl ? page + 1 : page - 1);
9730f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            CellLayout rightPage = (CellLayout) workspace.getChildAt(mIsRtl ? page - 1 : page + 1);
9740f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9750f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            if (leftPage != null && leftPage.isDragTarget()) {
9760f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ?
9770f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                        mLeftHoverDrawableActive : mLeftHoverDrawable;
9780f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                left.setBounds(0, mScrollChildPosition.top,
9790f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                        left.getIntrinsicWidth(), mScrollChildPosition.bottom);
9800f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                left.draw(canvas);
9810f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            }
9820f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            if (rightPage != null && rightPage.isDragTarget()) {
9830f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ?
9840f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                        mRightHoverDrawableActive : mRightHoverDrawable;
9850f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                right.setBounds(width - right.getIntrinsicWidth(),
9860f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                        mScrollChildPosition.top, width, mScrollChildPosition.bottom);
9870f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham                right.draw(canvas);
9880f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            }
9890f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        }
9900f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
9910f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9920f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
9930f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        boolean ret = super.drawChild(canvas, child, drawingTime);
9940f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
9950f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        // We want to draw the page hints above the workspace, but below the drag view.
9960f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        if (child instanceof Workspace) {
9970f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham            drawPageHints(canvas);
9980f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        }
9990f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham        return ret;
10000f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham    }
10010f97b7874fe29f36e7a40d2fe4b45d1e0e24fe1bTony Wickham
10026c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public void setBackgroundAlpha(float alpha) {
10036c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        if (alpha != mBackgroundAlpha) {
10046c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            mBackgroundAlpha = alpha;
10056c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen            invalidate();
10066c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        }
10076c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
10086c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
10096c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    public float getBackgroundAlpha() {
10106c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen        return mBackgroundAlpha;
10116c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen    }
10126c5891a9fce95eee3d87823d11d21889743e9c68Adam Cohen
1013b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public void setTouchCompleteListener(TouchCompleteListener listener) {
1014b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        mTouchCompleteListener = listener;
1015b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
1016b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen
1017b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    public interface TouchCompleteListener {
1018b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen        public void onTouchComplete();
1019b0f3d74815417acc3a9d3dce90cbf34b772847f0Adam Cohen    }
102031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1021