14c98d9235d164680186180974719f551cf935d08Winson Chung/*
24c98d9235d164680186180974719f551cf935d08Winson Chung * Copyright (C) 2011 The Android Open Source Project
34c98d9235d164680186180974719f551cf935d08Winson Chung *
44c98d9235d164680186180974719f551cf935d08Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
54c98d9235d164680186180974719f551cf935d08Winson Chung * you may not use this file except in compliance with the License.
64c98d9235d164680186180974719f551cf935d08Winson Chung * You may obtain a copy of the License at
74c98d9235d164680186180974719f551cf935d08Winson Chung *
84c98d9235d164680186180974719f551cf935d08Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
94c98d9235d164680186180974719f551cf935d08Winson Chung *
104c98d9235d164680186180974719f551cf935d08Winson Chung * Unless required by applicable law or agreed to in writing, software
114c98d9235d164680186180974719f551cf935d08Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
124c98d9235d164680186180974719f551cf935d08Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c98d9235d164680186180974719f551cf935d08Winson Chung * See the License for the specific language governing permissions and
144c98d9235d164680186180974719f551cf935d08Winson Chung * limitations under the License.
154c98d9235d164680186180974719f551cf935d08Winson Chung */
164c98d9235d164680186180974719f551cf935d08Winson Chung
174c98d9235d164680186180974719f551cf935d08Winson Chungpackage com.android.launcher2;
184c98d9235d164680186180974719f551cf935d08Winson Chung
19043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.TimeInterpolator;
20043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator;
21043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator.AnimatorUpdateListener;
224c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.Context;
23a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chungimport android.content.res.ColorStateList;
24201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chungimport android.content.res.Configuration;
254c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.res.Resources;
26043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF;
27d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.graphics.Rect;
28967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chungimport android.graphics.drawable.TransitionDrawable;
29b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monkimport android.os.UserManager;
304c98d9235d164680186180974719f551cf935d08Winson Chungimport android.util.AttributeSet;
314c98d9235d164680186180974719f551cf935d08Winson Chungimport android.view.View;
32043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.ViewConfiguration;
33a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chungimport android.view.ViewGroup;
34043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.animation.AnimationUtils;
35d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.view.animation.DecelerateInterpolator;
3661967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chungimport android.view.animation.LinearInterpolator;
374c98d9235d164680186180974719f551cf935d08Winson Chung
384c98d9235d164680186180974719f551cf935d08Winson Chungimport com.android.launcher.R;
394c98d9235d164680186180974719f551cf935d08Winson Chung
4061fa4197c4316bb0f9b05fcefb676f86197a2273Winson Chungpublic class DeleteDropTarget extends ButtonDropTarget {
41043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int DELETE_ANIMATION_DURATION = 285;
426e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung    private static int FLING_DELETE_ANIMATION_DURATION = 350;
436e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung    private static float FLING_TO_DELETE_FRICTION = 0.035f;
44043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int MODE_FLING_DELETE_TO_TRASH = 0;
45043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
46043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
47043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR;
484c98d9235d164680186180974719f551cf935d08Winson Chung
49a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chung    private ColorStateList mOriginalTextColor;
50ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mUninstallDrawable;
51ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mRemoveDrawable;
52ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mCurrentDrawable;
534c98d9235d164680186180974719f551cf935d08Winson Chung
544c98d9235d164680186180974719f551cf935d08Winson Chung    public DeleteDropTarget(Context context, AttributeSet attrs) {
554c98d9235d164680186180974719f551cf935d08Winson Chung        this(context, attrs, 0);
564c98d9235d164680186180974719f551cf935d08Winson Chung    }
574c98d9235d164680186180974719f551cf935d08Winson Chung
584c98d9235d164680186180974719f551cf935d08Winson Chung    public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
594c98d9235d164680186180974719f551cf935d08Winson Chung        super(context, attrs, defStyle);
604c98d9235d164680186180974719f551cf935d08Winson Chung    }
614c98d9235d164680186180974719f551cf935d08Winson Chung
624c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
634c98d9235d164680186180974719f551cf935d08Winson Chung    protected void onFinishInflate() {
644c98d9235d164680186180974719f551cf935d08Winson Chung        super.onFinishInflate();
654c98d9235d164680186180974719f551cf935d08Winson Chung
664c98d9235d164680186180974719f551cf935d08Winson Chung        // Get the drawable
67a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung        mOriginalTextColor = getTextColors();
684c98d9235d164680186180974719f551cf935d08Winson Chung
694c98d9235d164680186180974719f551cf935d08Winson Chung        // Get the hover color
704c98d9235d164680186180974719f551cf935d08Winson Chung        Resources r = getResources();
714c98d9235d164680186180974719f551cf935d08Winson Chung        mHoverColor = r.getColor(R.color.delete_target_hover_tint);
72ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mUninstallDrawable = (TransitionDrawable)
73ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen                r.getDrawable(R.drawable.uninstall_target_selector);
74ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector);
75ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
76ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mRemoveDrawable.setCrossFadeEnabled(true);
77ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mUninstallDrawable.setCrossFadeEnabled(true);
78ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
79ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        // The current drawable is set to either the remove drawable or the uninstall drawable
80ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        // and is initially set to the remove drawable, as set in the layout xml.
81947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
82201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung
83201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        // Remove the text in the Phone UI in landscape
84201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        int orientation = getResources().getConfiguration().orientation;
85201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
86201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung            if (!LauncherApplication.isScreenLarge()) {
87a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung                setText("");
88201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung            }
89201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        }
904c98d9235d164680186180974719f551cf935d08Winson Chung    }
914c98d9235d164680186180974719f551cf935d08Winson Chung
924c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isAllAppsApplication(DragSource source, Object info) {
934c98d9235d164680186180974719f551cf935d08Winson Chung        return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
944c98d9235d164680186180974719f551cf935d08Winson Chung    }
954c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isAllAppsWidget(DragSource source, Object info) {
9611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        if (source instanceof AppsCustomizePagedView) {
9711a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung            if (info instanceof PendingAddItemInfo) {
9811a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                PendingAddItemInfo addInfo = (PendingAddItemInfo) info;
9911a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                switch (addInfo.itemType) {
10011a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
10111a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                    case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
10211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                        return true;
10311a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                }
10411a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung            }
10511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        }
10611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        return false;
1074c98d9235d164680186180974719f551cf935d08Winson Chung    }
1080b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isDragSourceWorkspaceOrFolder(DragObject d) {
1090b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder);
1104c98d9235d164680186180974719f551cf935d08Winson Chung    }
1110b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isWorkspaceOrFolderApplication(DragObject d) {
1120b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo);
1130b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    }
1140b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isWorkspaceOrFolderWidget(DragObject d) {
1150b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo);
1164c98d9235d164680186180974719f551cf935d08Winson Chung    }
1174c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isWorkspaceFolder(DragObject d) {
1184c98d9235d164680186180974719f551cf935d08Winson Chung        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
1194c98d9235d164680186180974719f551cf935d08Winson Chung    }
1204c98d9235d164680186180974719f551cf935d08Winson Chung
121a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    private void setHoverColor() {
122a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mCurrentDrawable.startTransition(mTransitionDuration);
123a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setTextColor(mHoverColor);
124a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
125a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    private void resetHoverColor() {
126a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        mCurrentDrawable.resetTransition();
127a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setTextColor(mOriginalTextColor);
128a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
129a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
1304c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
1314c98d9235d164680186180974719f551cf935d08Winson Chung    public boolean acceptDrop(DragObject d) {
1324c98d9235d164680186180974719f551cf935d08Winson Chung        // We can remove everything including App shortcuts, folders, widgets, etc.
1334c98d9235d164680186180974719f551cf935d08Winson Chung        return true;
1344c98d9235d164680186180974719f551cf935d08Winson Chung    }
1354c98d9235d164680186180974719f551cf935d08Winson Chung
1364c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
1374c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragStart(DragSource source, Object info, int dragAction) {
1384c98d9235d164680186180974719f551cf935d08Winson Chung        boolean isVisible = true;
1394c98d9235d164680186180974719f551cf935d08Winson Chung        boolean isUninstall = false;
1404c98d9235d164680186180974719f551cf935d08Winson Chung
141f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        // If we are dragging a widget from AppsCustomize, hide the delete target
1424c98d9235d164680186180974719f551cf935d08Winson Chung        if (isAllAppsWidget(source, info)) {
1434c98d9235d164680186180974719f551cf935d08Winson Chung            isVisible = false;
1444c98d9235d164680186180974719f551cf935d08Winson Chung        }
1454c98d9235d164680186180974719f551cf935d08Winson Chung
1464c98d9235d164680186180974719f551cf935d08Winson Chung        // If we are dragging an application from AppsCustomize, only show the control if we can
1474c98d9235d164680186180974719f551cf935d08Winson Chung        // delete the app (it was downloaded), and rename the string to "uninstall" in such a case
1484c98d9235d164680186180974719f551cf935d08Winson Chung        if (isAllAppsApplication(source, info)) {
1494c98d9235d164680186180974719f551cf935d08Winson Chung            ApplicationInfo appInfo = (ApplicationInfo) info;
1504c98d9235d164680186180974719f551cf935d08Winson Chung            if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
1514c98d9235d164680186180974719f551cf935d08Winson Chung                isUninstall = true;
1524c98d9235d164680186180974719f551cf935d08Winson Chung            } else {
1534c98d9235d164680186180974719f551cf935d08Winson Chung                isVisible = false;
1544c98d9235d164680186180974719f551cf935d08Winson Chung            }
155b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk            // If the user is not allowed to access the app details page or uninstall, then don't
156b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk            // let them uninstall from here either.
157b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk            UserManager userManager = (UserManager)
158b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk                    getContext().getSystemService(Context.USER_SERVICE);
159b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk            if (userManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL)
160b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk                    || userManager.hasUserRestriction(UserManager.DISALLOW_UNINSTALL_APPS)) {
161b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk                isVisible = false;
162b407e0ab9bcdc8c58cf5ac31fed8031349304cd7Jason Monk            }
1634c98d9235d164680186180974719f551cf935d08Winson Chung        }
1644c98d9235d164680186180974719f551cf935d08Winson Chung
165ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (isUninstall) {
166d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio            setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
167ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        } else {
168d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio            setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null);
169ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        }
170947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
171ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
1724c98d9235d164680186180974719f551cf935d08Winson Chung        mActive = isVisible;
173a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        resetHoverColor();
174a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
175a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung        if (getText().length() > 0) {
176a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung            setText(isUninstall ? R.string.delete_target_uninstall_label
1774c98d9235d164680186180974719f551cf935d08Winson Chung                : R.string.delete_target_label);
1784c98d9235d164680186180974719f551cf935d08Winson Chung        }
1794c98d9235d164680186180974719f551cf935d08Winson Chung    }
1804c98d9235d164680186180974719f551cf935d08Winson Chung
1814c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
1824c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragEnd() {
1834c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragEnd();
1844c98d9235d164680186180974719f551cf935d08Winson Chung        mActive = false;
1854c98d9235d164680186180974719f551cf935d08Winson Chung    }
1864c98d9235d164680186180974719f551cf935d08Winson Chung
1874c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragEnter(DragObject d) {
1884c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragEnter(d);
1894c98d9235d164680186180974719f551cf935d08Winson Chung
190a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setHoverColor();
1914c98d9235d164680186180974719f551cf935d08Winson Chung    }
1924c98d9235d164680186180974719f551cf935d08Winson Chung
1934c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragExit(DragObject d) {
1944c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragExit(d);
1954c98d9235d164680186180974719f551cf935d08Winson Chung
196aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung        if (!d.dragComplete) {
197a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            resetHoverColor();
19861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        } else {
19961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung            // Restore the hover color if we are deleting
20061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung            d.dragView.setColor(mHoverColor);
201aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung        }
2024c98d9235d164680186180974719f551cf935d08Winson Chung    }
2034c98d9235d164680186180974719f551cf935d08Winson Chung
204ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    private void animateToTrashAndCompleteDrop(final DragObject d) {
205ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        DragLayer dragLayer = mLauncher.getDragLayer();
206ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        Rect from = new Rect();
207ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
20861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
20961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
21061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        float scale = (float) to.width() / from.width();
211ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
212d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        mSearchDropTargetBar.deferOnDragEnd();
213d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        Runnable onAnimationEndRunnable = new Runnable() {
214d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            @Override
215d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            public void run() {
216d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                mSearchDropTargetBar.onDragEnd();
217d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                mLauncher.exitSpringLoadedDragMode();
218d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                completeDrop(d);
219d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            }
220d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        };
22161967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
222d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
22361967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung                new LinearInterpolator(), onAnimationEndRunnable,
224ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                DragLayer.ANIMATION_END_DISAPPEAR, null);
225d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    }
226d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen
227d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    private void completeDrop(DragObject d) {
2284c98d9235d164680186180974719f551cf935d08Winson Chung        ItemInfo item = (ItemInfo) d.dragInfo;
2294c98d9235d164680186180974719f551cf935d08Winson Chung
2304c98d9235d164680186180974719f551cf935d08Winson Chung        if (isAllAppsApplication(d.dragSource, item)) {
2314c98d9235d164680186180974719f551cf935d08Winson Chung            // Uninstall the application if it is being dragged from AppsCustomize
23264c418361cf95057030df2abcfe893406052a0a2Kenny Guy            mLauncher.startApplicationUninstallActivity((ApplicationInfo) item, item.user);
2330b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        } else if (isWorkspaceOrFolderApplication(d)) {
2344c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteItemFromDatabase(mLauncher, item);
2354c98d9235d164680186180974719f551cf935d08Winson Chung        } else if (isWorkspaceFolder(d)) {
2364c98d9235d164680186180974719f551cf935d08Winson Chung            // Remove the folder from the workspace and delete the contents from launcher model
2374c98d9235d164680186180974719f551cf935d08Winson Chung            FolderInfo folderInfo = (FolderInfo) item;
2384c98d9235d164680186180974719f551cf935d08Winson Chung            mLauncher.removeFolder(folderInfo);
2394c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
2400b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        } else if (isWorkspaceOrFolderWidget(d)) {
2414c98d9235d164680186180974719f551cf935d08Winson Chung            // Remove the widget from the workspace
2424c98d9235d164680186180974719f551cf935d08Winson Chung            mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
2434c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteItemFromDatabase(mLauncher, item);
2444c98d9235d164680186180974719f551cf935d08Winson Chung
2454c98d9235d164680186180974719f551cf935d08Winson Chung            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
2464c98d9235d164680186180974719f551cf935d08Winson Chung            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
2474c98d9235d164680186180974719f551cf935d08Winson Chung            if (appWidgetHost != null) {
2484c98d9235d164680186180974719f551cf935d08Winson Chung                // Deleting an app widget ID is a void call but writes to disk before returning
2494c98d9235d164680186180974719f551cf935d08Winson Chung                // to the caller...
2504c98d9235d164680186180974719f551cf935d08Winson Chung                new Thread("deleteAppWidgetId") {
2514c98d9235d164680186180974719f551cf935d08Winson Chung                    public void run() {
2524c98d9235d164680186180974719f551cf935d08Winson Chung                        appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
2534c98d9235d164680186180974719f551cf935d08Winson Chung                    }
2544c98d9235d164680186180974719f551cf935d08Winson Chung                }.start();
2554c98d9235d164680186180974719f551cf935d08Winson Chung            }
2564c98d9235d164680186180974719f551cf935d08Winson Chung        }
2574c98d9235d164680186180974719f551cf935d08Winson Chung    }
258d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen
259d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    public void onDrop(DragObject d) {
260d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        animateToTrashAndCompleteDrop(d);
261d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    }
262043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
263043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
264043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Creates an animation from the current drag view to the delete trash icon.
265043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
266043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
267043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            DragObject d, PointF vel, ViewConfiguration config) {
268043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
269043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight());
270043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect from = new Rect();
271043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
272043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
273043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Calculate how far along the velocity vector we should put the intermediate point on
274043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // the bezier curve
275043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        float velocity = Math.abs(vel.length());
276043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f));
277043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        int offsetY = (int) (-from.top * vp);
278043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        int offsetX = (int) (offsetY / (vel.y / vel.x));
279043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y2 = from.top + offsetY;                        // intermediate t/l
280043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x2 = from.left + offsetX;
281043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x1 = from.left;                                 // drag view t/l
282043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y1 = from.top;
283043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x3 = to.left;                                   // delete target t/l
284043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y3 = to.top;
285043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
286043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() {
287043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
288043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public float getInterpolation(float t) {
289043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return t * t * t * t * t * t * t * t;
290043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
291043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
292043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        return new AnimatorUpdateListener() {
293043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
294043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public void onAnimationUpdate(ValueAnimator animation) {
295043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                final DragView dragView = (DragView) dragLayer.getAnimatedView();
296043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float t = ((Float) animation.getAnimatedValue()).floatValue();
297043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float tp = scaleAlphaInterpolator.getInterpolation(t);
298043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float initialScale = dragView.getInitialScale();
299043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float finalAlpha = 0.5f;
300043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float scale = dragView.getScaleX();
301043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f;
302043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f;
303043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) +
304043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        (t * t) * x3;
305043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) +
306043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        (t * t) * y3;
307043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
308043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setTranslationX(x);
309043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setTranslationY(y);
310043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setScaleX(initialScale * (1f - tp));
311043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setScaleY(initialScale * (1f - tp));
312043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp));
313043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
314043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
315043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
316043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
317043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
318043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Creates an animation from the current drag view along its current velocity vector.
319043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * For this animation, the alpha runs for a fixed duration and we update the position
320043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * progressively.
321043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
322043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
323043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private DragLayer mDragLayer;
324043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private PointF mVelocity;
325043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private Rect mFrom;
326043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private long mPrevTime;
327043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private boolean mHasOffsetForScale;
3286e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        private float mFriction;
329043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
3309658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung        private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
331043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
332043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
3336e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                long startTime, float friction) {
334043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragLayer = dragLayer;
335043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocity = vel;
336043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom = from;
337043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mPrevTime = startTime;
3386e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
339043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
340043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
341043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        @Override
342043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        public void onAnimationUpdate(ValueAnimator animation) {
343043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final DragView dragView = (DragView) mDragLayer.getAnimatedView();
344043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            float t = ((Float) animation.getAnimatedValue()).floatValue();
345043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            long curTime = AnimationUtils.currentAnimationTimeMillis();
346043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
347043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (!mHasOffsetForScale) {
348043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mHasOffsetForScale = true;
349043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float scale = dragView.getScaleX();
350043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f;
351043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f;
352043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
353043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mFrom.left += xOffset;
354043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mFrom.top += yOffset;
355043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
356043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
357043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
358043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
359043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
360043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setTranslationX(mFrom.left);
361043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setTranslationY(mFrom.top);
362043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
363043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
3646e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mVelocity.x *= mFriction;
3656e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mVelocity.y *= mFriction;
366043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mPrevTime = curTime;
367043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
368043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    };
369043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
370043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            DragObject d, PointF vel, final long startTime, final int duration,
371043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            ViewConfiguration config) {
372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect from = new Rect();
373043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
374043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
3756e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
3766e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                FLING_TO_DELETE_FRICTION);
377043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
378043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
380a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView;
381a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Don't highlight the icon as it's animating
383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        d.dragView.setColor(0);
384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        d.dragView.updateInitialScaleToCurrentScale();
385a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        // Don't highlight the target if we are flinging from AllApps
386a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        if (isAllApps) {
387a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            resetHoverColor();
388a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        }
389043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
390043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
391043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Defer animating out the drop target if we are animating to it
392043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mSearchDropTargetBar.deferOnDragEnd();
393043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mSearchDropTargetBar.finishAnimations();
394043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
395043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
396043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final ViewConfiguration config = ViewConfiguration.get(mLauncher);
397043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final DragLayer dragLayer = mLauncher.getDragLayer();
3986e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        final int duration = FLING_DELETE_ANIMATION_DURATION;
399043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final long startTime = AnimationUtils.currentAnimationTimeMillis();
400043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
401043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // NOTE: Because it takes time for the first frame of animation to actually be
402043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // called and we expect the animation to be a continuation of the fling, we have
403043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // to account for the time that has elapsed since the fling finished.  And since
404043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // we don't have a startDelay, we will always get call to update when we call
405043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // start() (which we want to ignore).
406043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final TimeInterpolator tInterpolator = new TimeInterpolator() {
407043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            private int mCount = -1;
408043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            private float mOffset = 0f;
409043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
410043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
411043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public float getInterpolation(float t) {
412043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (mCount < 0) {
413043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mCount++;
414043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                } else if (mCount == 0) {
415043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
416043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                            startTime) / duration);
417043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mCount++;
418043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
419043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return Math.min(1f, mOffset + t);
420043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
421043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
422043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = null;
423043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
424043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config);
425043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) {
426043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime,
427043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    duration, config);
428043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
429043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        Runnable onAnimationEndRunnable = new Runnable() {
430043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
431043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public void run() {
432a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up
433a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                // itself, otherwise, complete the drop to initiate the deletion process
434a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                if (!isAllApps) {
435a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                    mLauncher.exitSpringLoadedDragMode();
436a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                    completeDrop(d);
437a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                }
438a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                mLauncher.getDragController().onDeferredEndFling(d);
439043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
440043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
441043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
442043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                DragLayer.ANIMATION_END_DISAPPEAR, null);
443043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
4444c98d9235d164680186180974719f551cf935d08Winson Chung}
445